zoukankan      html  css  js  c++  java
  • 安卓权威编程指南 -笔记(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 值以取出颜色。取出颜色值之后就可以使用了,比如,用来更改按钮背景色。

  • 相关阅读:
    Vim 在 windows 环境下的初步配置
    空间向量在任意平面的投影公式推导 (矩阵方法)
    jquery中获取元素的几种方式小结
    开源框架
    将插入的新行放入dataGridView的第一行
    go-mod 入门
    docker 常用启动命令
    golang str 首字母大写
    遇到过的几个难搞的问题
    jwt、session、oauth 异同
  • 原文地址:https://www.cnblogs.com/chase1/p/7198630.html
Copyright © 2011-2022 走看看