Android style & Theme 再探析(四)

业务实践心得总结

基于前几篇的探究,我们已经有了对一个app的theme和style的理论探究和demo描述了不少,那么接下来针对我在自己在app生产环境中的使用的一个使用心得总结

Android Theme的生产环境使用总结



本篇主要针对小伙伴如果要在自己的app中实践,整理以前混乱的theme和style的一个实践

针对Theme配置的一些建议

如果大家按本文第一章的方式设定Theme时,一定要注意几点:

文字颜色一定要设置小心,由于Theme具有继承性,所以文字颜色的设定会被Android本身的style的继承结构沿用到其子类;但是,在沿用其子类时,有时会进行一定配置的重写,而此时重写的配置就会变为一个不可控因素,产生意想不到的bug

示例:
笔者在使用时,设定了这样的配置

<style name="ThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
        <!--忽略部分代码-->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="buttonStyle">@style/EhiTheme.Button</item>
    </style>
    <!--主题修改为使用最新-->
    <style name="EhiTheme" parent="ThemeBase">
        <!--定义v21 之前api的内容-->
    </style>
      <!--重写button默认样式-->
     <style name="EhiTheme.Button" parent="@style/Widget.AppCompat.Button">
        <item name="android:background">@drawable/btn_default_ehi_selector</item>
        <item name="android:textColor">@color/white</item>
    </style>

代码可以看的出,此为一个button的默认样式修改;而这份代码关键就在于

<item name="android:textColor">@color/white</item>

这句代码将按钮文字设置为白色十分危险,因为Android中很多控件都会沿用这部分的样式;但是,同时这个部分的样式针对各个版本的Android系统上也是有着不同的体现!

以下是不同版本下,此重写样式后AlertDialog的不同体现


Android 8.0
Android 6.0

通过上图可以看到,在Android 6.0的弹窗上,文字采用了colorAccent的颜色,而Android8.0则采用了文字继承下来的白色;但是两者在显示上的一个共同点就是,背景都被置空;这就造成了白色背景加上白色字体的显示bug!

a>同时,要特别注意的一点是,这样的bug不止存在alertDialog,同样会反映在 timePickDialog和datePickDialog上面!
b>另外,需要大家注意的是,在v7包下的alertDialog和app包下的alertDialog是读取的两套设定

v7包:

 <item name="alertDialogTheme"></item>

app系统包下:

<item name="android:alertDialogTheme"></item>

如果项目在使用上不规范的情况下,很可能两种dialog都会引入进行使用,那么两种其一不起作用,都会有产生Bug的风险!
解决方案:
针对Dialog的Theme主题部分,进行重写

定义Alert自己的Theme:

colors.xml

<color name="colorAccent">#FFFF7E00</color>

Themes.xml

    <style name="EhiTheme.AlertDialog" parent="Theme.AppCompat.Light.Dialog.Alert">
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:textColor">@color/colorAccent</item>
        <item name="buttonStyle">@style/EhiTheme.Button.Alert</item>
    </style>

    <style name="EhiTheme.Button.Alert" parent="@style/Widget.AppCompat.Button">
        <item name="android:background">@color/white</item>
        <item name="android:textColor">@color/colorAccent</item>
    </style>

<style name="ThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
        <!--定义v7 之后所有api的内容-->
        <!--基本主题色-->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <!--部分忽略-->
        <item name="buttonStyle">@style/EhiTheme.Button</item>
        <item name="alertDialogTheme">@style/EhiTheme.AlertDialog</item>
         <item name="android:alertDialogTheme">@style/EhiTheme.AlertDialog</item>
    </style>
       

v21中Themes.xml

     <style name="EhiTheme" parent="ThemeBase">
        <!--定义v21 之后api的内容-->
        <item name="android:timePickerDialogTheme">?alertDialogTheme</item>
        <item name="android:datePickerDialogTheme">?alertDialogTheme</item>
        <item name="android:alertDialogTheme">?alertDialogTheme</item>
    </style>

代码中,如果结构不好有多个baseActivity基类一定要注意!父类在继承FragmentActivityAppCompatActivity时,其展现形式是不一样的,由于AppCompatActivity在为了保证变为统一样式在内部做了很多封装;(ps:theme继承了的情况下Theme.AppCompat.Light.NoActionBar;使用基础activity会crash),需要在添加后测试一下

针对view自定义属性

自定义控件的属性的命名的一点小建议:

以前我们的自定义view属性的命名全凭喜好
主流的一般有这样的,小驼峰的命名形式

<declare-styleable name="EhiTitleBar">
    
        <attr name="isSearchView" format="boolean"/>
        <attr name="searchViewHint" format="string" />
        <attr name="titleBackground" format="color|reference" />
    </declare-styleable>

还有下划线大法的

<declare-styleable name="EhiDrawingBoard">
        <attr name="stroke_width" format="integer"/>
        <attr name="paint_color" format="color"/>
        <attr name="canvas_color" format="color|reference"/>
        <attr name="anti_alias" format="boolean"/>
    </declare-styleable>

但是我认为很多内容的使用,我们都应该更接近原生控件的使用:

例如textView

<TextView
        android:id="@+id/text_type"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="今天"
        android:layout_marginLeft="10dp"
        android:textColor="@color/black"
        android:textSize="18sp" />

可以看的出android的控件命名其实是分成两部分
属性是作用于其子类本身的内部,像这样的文本尺寸

android:textSize="18sp"

采用了小驼峰法

而属性比如是作用于控件的类似layoutparam这种和父类相关的属性

android:layout_height="wrap_content"

以下划线来区分,这样其实我觉得对于学习和接受度其实都可以很快,毕竟在使用原始控件时的方式都类似

Style命名的一点小建议

style的使用命名规范的一点小建议

以前的style我们是这么命名的:

<!-- 条目标签样式 -->
   <style name="item_reimburse_label">
       <item name="android:layout_width">0dp</item>
       <item name="android:layout_height">wrap_content</item>
       <item name="android:layout_weight">0.3</item>
   </style>

但是,这种命名其实非常凌乱,

  • 看不出style的层级关系,继承关系
  • 看不出它所属的模块;所以在比较大的项目工程中,在上方使用者调用会非常混乱
  • style的统一管理十分困难,有差不多的一组style有样式改动,将会是一个灾难
  • 组件化后,各个模块容易出现命名重复问题

后来我们进行了一点优化

<!--myorder是module名-->
 <style name="myorder_item_reimburse_label">
        <item name="android:layout_width">0dp</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_weight">0.3</item>
    </style>

命名虽然看的出模块所属,但是我觉得没有充分将style的功能发挥出来,使用也并不怎么友好!

我认为比较适合我们在大型项目中工程化的style的命名是需要更向系统的style命名形式靠拢的:

一般我们可以采用大驼峰的命名形式,以 . 作为各种应用场景的区分

Module.页面.控件类型.控件修饰描述

    <!--总模块-->
    <style name="CompanyInfo" />
     <!--总模块,所属界面-->
    <style name="CompanyInfo.DriverMangerSearchOrderResult" />
     <!--总模块,所属界面.对应控件-->
    <style name="CompanyInfo.DriverMangerSearchOrderResult.ItemLabelContent">
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_marginTop">@dimen/tv_order_content_margin_top</item>
        <item name="android:ellipsize">end</item>
    </style>
      <!--总模块,所属界面.对应控件.控件应用场景描述-->
     <style name="CompanyInfo.DriverMangerSearchOrderResult.ItemLabelContent.NoBackground">
        <item name="android:background">@null</item>
    </style>

可是,我们很多情况下会有很多界面共用同样的样式,所以为了这种情况,我们可以利用 style的显示继承
首先,定义一个公共模块的样式

<!--labelContentView的Style-->
    <style name="EhiBase.Widget.LabelContent">
        <!--部分忽略-->
        <item name="contentColor">@color/colorGray100</item>
        <item name="contentHintColor">@color/colorGray350</item>
    </style>

然后,在自己的module里面直接进行引用,这样,在同时保证了命名的统一的同时,还兼顾的使用通用样式

<!--用于个人管理模块-->
    <style name="PersonalManager" />
    <!--个人信息界面-->
    <style name="PersonalManager.MyInformation" />
    <!--利用显示继承,使用通用样式-->
    <style name="PersonalManager.MyInformation.LabelContent" parent="EhiBase.Widget.LabelContent"/>
     

这样有以下优势

  • 有统一的模块描述,页面描述,控件描述;
  • 能够更好使得命名空间不冲突
  • 同时利用 style的显式继承可以做到对控件的统一管控
  • 类似Android原生的用法,上手更快

部分源码展示

 <style name="Theme.AppCompat" parent="Base.Theme.AppCompat"/>
    <style name="Theme.AppCompat.CompactMenu" parent="Base.Theme.AppCompat.CompactMenu"/>
    <style name="Theme.AppCompat.DayNight" parent="Theme.AppCompat.Light"/>
    <style name="Theme.AppCompat.DayNight.DarkActionBar" parent="Theme.AppCompat.Light.DarkActionBar"/>
    <style name="Theme.AppCompat.DayNight.Dialog" parent="Theme.AppCompat.Light.Dialog"/>
    <style name="Theme.AppCompat.DayNight.Dialog.Alert" parent="Theme.AppCompat.Light.Dialog.Alert"/>

隐式继承控制命名的完整性,显式继承控制模块与模块之间的通用部分

专题系列:
Android style & Theme 再探析(一)—— 你真的懂Style和Theme吗?
Android style & Theme 再探析(二) —— 一统View规范的大杀器——material design
Android style & Theme 再探析(三) —— 定制Theme示例和日夜间模式踩坑大汇总
Android style & Theme 再探析(四) —— 业务实践心得总结
博主博客:
http://www.whdreamblog.cn/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容