安卓权威编程指南 -笔记(20章 样式与主题)

1.颜色资源

在res/values/color.xml内可以定义一些颜色供应用引用。

2.样式

样式是一套能够应用于视图组件的属性,用于复用相同的 UI 特性。

在res/values/styles.xml中添加一个BeatBoxButton样式。

2.1 添加样式
 <style name="BeatBoxButton">
        <item name="android:background">@color/drak_blue</item>
    </style>
2.2 通过下面这种方式就可以使用样式
<Button
    ......
    style="@style/BeatBoxButton"
    ......
    />
2.3 样式支持继承,一个样式能继承并覆盖其他样式的属性。

继承方式一: 通过.Strong继承

<style name="BeatBoxButton.Strong">
    <item name="android:textStyle">bold</item>
</style>

继承方式二 : 通过指定父样式的形式

<style name="BeatBoxButton.Strong">
    <item name="android:textStyle">bold</item>
</style>

3.主题

样式很有用。在styles.xml公共文件中,可以为所有组件定义一套样式属性共用。可惜,定义公共样式属性虽方便,实际应用却很麻烦:需要逐个为所有组件添加它们要用到的样式。要是开发一个复杂应用,涉及很多布局、无数按钮,仅仅添加样式就需要巨大的工作量。该是主题闪亮登场的时候了!可以把主题看作样式的进化加强版。同样是定义一套公共主题属性,样式属性需要逐个添加,而主题属性则会自动应用于整个应用。主题属性能引用颜色这样的外部资源,也能引用其他样式。使用主题,可以简单地说:“所有按钮都使用这个样式。”再也不用找到每个按钮,告诉它们要用哪个主题了。

3.1修改默认主题

找到并打开AndroidManifest.xml文件,可以看到 application标签下的 theme 属性。

 android:theme="@style/AppTheme"

theme属性指向的主题叫AppTheme,他也是定义在styles.xml文件中。

主题实际就是一种样式,但主题指定的属性有别于样式。

在 manifest 文件中我们看到整个应用的主题是Android:theme="@style/AppTheme",按住 Command(Windows 下是 Ctrl),点击 AppTheme 就可以进入其声明的位置,可以看到以下代码:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
</style>

可以看到AppTheme继承Theme.AppCompat.Lighy.DarkActionBar的全部属性。如有需要,可以自己添加自己的属性值,或是覆盖父主题的某些属性值 。

AppCompat 库自带三大主题
- Theme.AppCompat——深色主题 
- Theme.AppCompat.Light——浅色主题 
- Theme.AppCompat.Light.DarkActionBar——带深色工具栏的浅色主题 

3.2 添加主题颜色

在styles.xml文件中,为AppTheme添加三个自定义属性。如下所示:

<style name="AppTheme" parent="Theme.AppCompat">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/red</item>
        <item name="colorPrimaryDark">@color/drak_red</item>
        <item name="colorAccent">@color/gray</item>
    </style>

colorPrimary 属性主要用来设置工具栏背景色。由于应用名称是显示在工具栏上的,colorPrimary 也可以称为应用品牌色。

colorPrimaryDark 用于屏幕顶部的状态栏。从名字可以看出,它是深色版 colorPrimary 。注意,只有Lollipop以后的系统支持状态栏主题色。对于之前的系统,无论指定什么主题色,状态栏都是不变的黑底色。

最后,将 colorAccent 设置为灰色的。这个主题色应该和 colorPrimary 形成反差效果,主要用于给 EditText 这样的组件着色。

3.3 主题探秘

我们的首个目标是修改主题以改变BeatBox应用的背景色。当然,你可以打开res/layout/
fragment_beat_box.xml文件,手工设置 RecyclerView 视图的 android:background 属性。如果还
有其他fragment和activity要改,都照此处理。这简直是浪费:浪费时间,浪费系统资源。
主题已经设置了背景色,在此基础上再设置其他颜色,就是多出来在做额外的工作。而且,
在应用里到处复制使用背景属性设置代码也不利于后期维护。

要解决上述问题,应设法覆盖主题背景色属性。为了找出可覆盖属性的名字,先来看看这个属性在其父主题里是怎么设置的: Theme.AppCompat 。

你需要找出主题继承的源头。主题继承树有多少深,谁也不知道,只能一层层向上找,直到找到AppCompat库的外面。

打开styles.xml文件,按住Command键(Windows系统是Ctrl键)点击 Theme.AppCompat ,来看看继承有多深。

 第一层

Android开发工具更新频繁,本书编写时,Android Studio会定位到一个大文件的这行:
<style name="Theme.AppCompat" parent="Base.Theme.AppCompat" />
Theme.AppCompat 主题属性继承自 Base.Theme.AppCompat 。有趣的是, Theme.AppCompat
本身没有覆盖任何属性,仅仅指向了其父主题。

 第二层

按住Command键再点击 Base.Theme.AppCompat ,Android Studio会提示这个主题有多个版本。
选择values-v21/values.xml版本.  

<style name="Base.Theme.AppCompat" parent="Base.V21.Theme.AppCompat"/>

这一层仍是空主题。继续往后上找

第三层

<style name="Base.V21.Theme.AppCompat"parent="Base.V7.Theme.AppCompat">

这一层出现了很多属性,但依旧没有我们想要的背景色属性。所以继续网上找。

第四层

依旧没有,继续往上

<style name="Base.V7.Theme.AppCompat" parent="Platform.AppCompat">

第五层

空主题,往上。

<style name="Platform.AppCompat" parent="Platform.V11.AppCompat"/>

第六层

没有我们想要的属性,继续往上。

<style name="Platform.V11.AppCompat" parent="android:Theme.Holo">

第七层

总算找到了。在这里,终于可以看到所有可以覆盖的主题属性。

<style name="Theme.Holo">
<item name="colorForeground">@color/bright_foreground_holo_dark</item>
<item name="colorForegroundInverse"></item>
<item name="colorBackground">@color/background_holo_dark</item>
...
</style>

这也是要在BeatBox应用中覆盖的属性。回到styles.xml文件中,覆盖 colorBackground 这个
属性。

设置窗口背景颜色

   <style name="AppTheme" parent="Theme.AppCompat">
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/red</item>
            <item name="colorPrimaryDark">@color/drak_red</item>
            <item name="colorAccent">@color/gray</item>
            <item name="android:colorBackground">@color/soothing_blue</item>
        </style>

注意, colorBackground 这个属性来自Android操作系统,所以别忘了使用 android 命名空间。

3.4  修改按钮属性

我们通过在res/layout/list_item_sound.xml文件中手工设置样式属性,定制过BeatBox应用的按钮。如果一个复杂应用有很多带按钮的fragment,再去逐个fragment、逐个按钮地去设置 style属性就很不应该了。在这种情况下,还是要靠主题。

再次定位查看 Theme.Holo 主题定义,查找按钮属性。

<item name="buttonStyle">@style/Widget.Holo.Button</item>

注意到有个 buttonStyle 属性,这是应用中普通按钮的样式。

这个 buttonStyle 属性没有设置值,而是指向了一个样式资源。前面覆盖 colorBackground属性时,直接传入了颜色值。这里, buttonStyle 应该指向另一个样式。定位并查看 Widget.Holo.Button 样式。

<style name="Widget.Holo.Button" parent="Widget.Button">
        <item name="background">@drawable/btn_default_holo_dark</item>
        <item name="textAppearance">?attr/textAppearanceMedium</item>
        <item name="textColor">@color/primary_text_holo_dark</item>
        <item name="minHeight">48dip</item>
        <item name="minWidth">64dip</item>
    </style>

BeatBox应用中所有按钮都使用了这些属性。

在BeatBox应用里,复用Android自身主题。修改 BeatBoxButton 样式的父样式为 android:
style/Widget.Holo.Button 。另外,删除 BeatBoxButton.Strong 样式。  

最后覆盖buttonStyle属性,让它指向BeatBoxButton样式。

3.5 样式继承拾遗

要是以主题名的形式指定父主题,有继承关系的两个主题都应处在同一个包中,因此,对于Android操作系统内部主题间的继承,就可以直接使用主题名继承表示法,同理,AppCompat库内部也是这样,然而,一旦AppCommpat库要跨库继承,就一定要明确使用parent属性。

在开发自己的应用时,应遵守同样的规则。如果是继承自己内部的主题,使用主题名指定父
主题即可;如果是继承Android操作系统中的样式或主题,记得使用 parent 属性。

3.6 引用主题属性

在XML中引用具体指(如颜色值),我们使用@符号,@color/gray指向某个特定资源。

在主题引用资源时,我们使用?符号。

android:background="?attr/colorAccent"

上述XML中?符号的意思是使用colorAccent属性指向的资源。

也可以在代码中使用主题属性,但是比较啰嗦:

Resources.Theme theme = getActivity().getTheme();
int[] attrsToFetch = { R.attr.colorAccent };
TypedArray a = theme.obtainStyledAttributes(R.style.AppTheme, attrsToFetch);
int accentColor = a.getInt(0, 0);
a.recycle();

先取得 Theme 对象,然后要求它找到定义在 AppTheme( 即 R.style.AppTheme) 中的R.attr.colorAccent 属性。结果得到一个持有数据的 TypedArray 对象。接着,向 TypedArray对象索要 int 值以取出颜色。取出颜色值之后就可以使用了,比如,用来更改按钮背景色。

原文地址:https://www.cnblogs.com/chase1/p/7198630.html