android 系统Style,Theme,以及自定义模板(declare-style)

来源:互联网 发布:武侠网络 编辑:程序博客网 时间:2024/05/07 15:21
1,系统的Style,Theme的关系链
在attrs.xml声明一种属性
<attr name="textColorHint" format="reference|color" />

|
|

在style_material.xml中引用这些attr
<style name="TextAppearance.Material">
         <item name="textColor">?attr/textColorPrimary</item>
         <item name="textColorHint">?attr/textColorHint</item>                                                                                            
         <item name="textColorHighlight">?attr/textColorHighlight</item>
         <item name="textColorLink">?attr/textColorLink</item>
         <item name="textSize">@dimen/text_size_body_1_material</item>
         <item name="fontFamily">@string/font_family_body_1_material</item>
</style>

|
|

styles_device_defaults.xml继承style_material.xml,
<style name="TextAppearance.DeviceDefault" parent="TextAppearance.Material"/> 

|
|
themes_device_defaults.xml定义了一组相关style
<style name="Theme.DeviceDefault" parent="Theme.Material" >
     <!-- Text styles -->
     <item name="textAppearance">@style/TextAppearance.DeviceDefault</item>                                                                                
      <item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>

...
</style>


|
|
那,到底在哪赋值的呢?看parent="Theme.Material"
./themes_material.xml
<style name="Theme.Material">
...
        <!-- Text styles -->
        <item name="textAppearance">@style/TextAppearance.Material</item>
        <item name="textAppearanceInverse">@style/TextAppearance.Material.Inverse</item>
...
</style>

|
|

在theme.xml中赋值(不同的theme赋不同的值)
<item name="textColorHint">@color/hint_foreground_dark</item>
|
|
引用的color值转成对应的16进制颜色Gray
<color name="hint_foreground_dark">#808080</color>

大致关系如下:
styles_device_defaults.xml     ——     themes_device_defaults.xml
|
style_material.xml             ——          themes_material.xml
|
style.xml                      ——       theme.xml



几个属性attr       ——     1个style
在style_material.xml中
<style name="TextAppearance.Material">
         <item name="textColor">?attr/textColorPrimary</item>
         <item name="textColorHint">?attr/textColorHint</item>                                                                                             
         <item name="textColorHighlight">?attr/textColorHighlight</item>
         <item name="textColorLink">?attr/textColorLink</item>
         <item name="textSize">@dimen/text_size_body_1_material</item>
         <item name="fontFamily">@string/font_family_body_1_material</item>
</style>

几个style     ——     1个theme
themes_device_defaults.xml定义了一组相关style
<style name="Theme.DeviceDefault" parent="Theme.Material" >
     <!-- Text styles -->
     <item name="textAppearance">@style/TextAppearance.DeviceDefault</item>                                                                                 
      <item name="textAppearanceInverse">@style/TextAppearance.DeviceDefault.Inverse</item>

...
</style>

        
2,系统控件的theme和style是怎么定义的?
以Button控件为例,使用最基本的theme.xml来分析。
在APK开发的过程,我们使用Button基本上这样使用
    <Button
        android:id="@+id/bt1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/checkBox1"
        android:text="This is Button1"
        android:textSize="22sp" />
对应出来一个Button

Button.java这个类,在构造的时候,可以看出来是使用哪种style
    public Button(Context context, AttributeSet attrs) {
        this(context, attrs, com.android.internal.R.attr.buttonStyle);
    }

->
attrs.xml
<attr name="buttonStyle" format="reference" />
这是一个引用类型,那么我们看,在哪赋值?以最基本的theme.xml来分析
->
theme.xml
<item name="buttonStyle">@style/Widget.Button</item>
->
style.xml这里Widget.Button是一组属性的集合
 333     <style name="Widget.Button">                                                                                                                         
334         <item name="background">@drawable/btn_default</item>
335         <item name="focusable">true</item>
336         <item name="clickable">true</item>
337         <item name="textAppearance">?attr/textAppearanceSmallInverse</item>
338         <item name="textColor">@color/primary_text_light</item>
339         <item name="gravity">center_vertical|center_horizontal</item>
340     </style>
来看一下backgroud这个属性
drawable/btn_default.xml定义了一些状态变化时候对应的属性值
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_window_focused="false" android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_window_focused="false" android:state_enabled="false"
        android:drawable="@drawable/btn_default_normal_disable" />
    <item android:state_pressed="true"
        android:drawable="@drawable/btn_default_pressed" />
    <item android:state_focused="true" android:state_enabled="true"
        android:drawable="@drawable/btn_default_selected" />
    <item android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_focused="true"                                                                                                                        
        android:drawable="@drawable/btn_default_normal_disable_focused" />
    <item
         android:drawable="@drawable/btn_default_normal_disable" />
</selector>


3,修改默认APP主题的一些属性。
从AndroidManifest.xml可以看出当前APK使用的是哪种Theme
android:theme ="@style/AppTheme" >
styles.xml
    <style name="AppBaseTheme" parent= "android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style >

    <!-- Application theme. -->
    <style name="AppTheme" parent= "AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
       
    </style >
从原始文件中可以看出,AppTheme继承自AppBaseTheme,继承自android:Theme.Light
framework/base/core/res/res/value/theme.xml
    <style name="Theme.Light">                                                                                                                                
        <item name="windowBackground">@drawable/screen_background_selector_light</item>
        <item name="windowClipToOutline">false</item>

        <item name="colorBackground">@color/background_light</item>
        <item name="colorForeground">@color/bright_foreground_light</item>
        <item name="colorForegroundInverse">@color/bright_foreground_light_inverse</item>
...
</style>
可以看到定义了Light主题的一些值,其实Light也是继续自Theme主题,只是Theme.Light是重写了一些sytele。
如果想要改变Theme.Light,比如说不要标题栏,
在theme主题下
<style name="Theme">
 <!-- Window attributes -->
<item name="windowNoTitle">false</item> 就是这个属性
</style>
 
那就生修改这个属性,修改styles.xml,注意要加上namespace即可。
    <!-- Application theme. -->
    <style name="AppTheme" parent= "AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
       <item name="android:windowNoTitle">true</item > //添加这行
    </style >



4,如果我想改一下控件的一些属性,当focus的时候,Button上面会一层浅蓝色,变成黄色。
 变成 
首先在theme.xml里面找Theme.Light有没有button相关的属性设置,没有。
那就找父类Theme里面Button的相关属性。其实在Button.java的构造函数可知是buttonStyle。

        <!-- Button styles -->
        <item name="buttonStyle">@style/Widget.Button</item>
 可以看到是引用Widget.Button 在styles.xml
    <style name="Widget.Button">
        <item name="background">@drawable/btn_default</item>                                                                                                  
        <item name="focusable">true</item>
        <item name="clickable">true</item>
        <item name="textAppearance">?attr/textAppearanceSmallInverse</item>
        <item name="textColor">@color/primary_text_light</item>
        <item name="gravity">center_vertical|center_horizontal</item>
    </style>
背景控制的属性是btn_default
drawable/btn_default.xml里面是一个selector,是不同状态时候的Button显示
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_window_focused="false" android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_window_focused="false" android:state_enabled="false"
        android:drawable="@drawable/btn_default_normal_disable" />
    <item android:state_pressed="true"
        android:drawable="@drawable/btn_default_pressed" />
    <item android:state_focused="true" android:state_enabled="true"
        android:drawable="@drawable/btn_default_selected" />
    <item android:state_enabled="true"
        android:drawable="@drawable/btn_default_normal" />
    <item android:state_focused="true"                                                                                                                        
        android:drawable="@drawable/btn_default_normal_disable_focused" />
    <item
         android:drawable="@drawable/btn_default_normal_disable" />
</selector>
同理,把btn_default.xml复制到app项目里面的draweable下面,同时把这些.9.png图片复制到draweable-hdpi下面,如下:
再在styles.xml里面重写buttonsytle如下:  为新增部分
    <!-- Application theme. -->
    <style name="AppTheme" parent= "AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
       <item name="android:windowNoTitle">true</item >
        <item name= "android:buttonStyle">@style/MyWidget.Button </item>
       
    </style >
   
    <style name="MyWidget.Button" parent= "@android:style/Widget.Button" >
        <item name= "android:background">@drawable/btn_default </item>
    </style >


完成。

0 0