写的非常好!

今天同事让我帮她改一下settings界面的的小标题栏的背景色,因为之前我有看过2.3系统的settings,所以就欣然答应了,没想到4.0的系统跟之前差别那么大,搞了两天才把这个小标题栏看明白。以前在2.3系统中,settings的小标题就是一个PerferenceCategory对象,如果想改背景色,直接在Preference_category.xml里加一个backgroudColor属性就可以了。但是现在这招不管用了,主要原因就是现在settings的小标题不是perferenceCategory了,查看settings的布局文件settings_headers.xml竟然全是清一色的[header]标签,瞬间不懂了,看起来标题栏和它下面的settings项的布局应该没啥区别了,因为都是标签相同的啊,可是明明他们的title字体风格一个大一个小啊?

    经过艰苦的寻找,终于在settings.java的onBuildHeaders方法里面发现了奥秘,这里调用了一个loadHeadersFromResource方法,这个方法是settings的父类PreferenceActivity定义的方法,功能就是解析含有标签的xml文件,这里就是用来解析settings_header.xml,解析的结果就是,所有的标签项都被转化成一个个的Header类对象,然后统一放到一个List链表中。那么怎么把链表里面的header对象变成可以让用户眼睛可以看到的View呢?没错!这里就要用到Adapter了,这里google自己写了一个headerAdapter,这个headerAdapter首先对链表里的header进行了分类,如果这个header不带有fragment 或者不带Intent那么它就会被看成是HEADER_TYPE_CATEGORY,也就是我一开始提到的小标题栏了,我特意又回去看了一下settings_headers.xml,发现确实用作小标题栏的header 标签 都没有带fragment或者intent属性,都只有一个title属性。接着在HeaderAdaper的getview方面里面,使用switch语句,对于不同的类型的header就会构造不同view。这里case到HEADER_TYPE_CATEGORY的时候就生成一个android.R.attr.listSeparatorTextViewStyle风格的TextView。从英文单词List Separator就可以知道这个风格就是我所说的小标题栏风格了。所以如果想改背景色,那就直接对这个Textview进行修改就可以了。

    但是这样改有一个局限性,就是生效的范围仅限于Setting的第一级菜单,而第二级第三级菜单依然没有变化,比如storage_setting下面的小标题栏还是原来的样子,所以需要想一个全局生效的方法,看了一下settings下面几级菜单的代码,发现google又没有用header了,还是和2.3系统一样,用的PreferenceCatorage

做为标题栏的类,这样看来问题就迎刃而解了,只要改一下Preference_category.xml的布局就可以了。但是改的时候我突然发现,Preference_category里面的TextView也是用的listSeparatorTextViewStyle风格。所以我就想到,如果统一改一下listSeparatorTextViewStyle风格的属性,就把问题集中解决了,就不用两处都改,弄的很麻烦!

    起初在headerAdapter里面,有一个地方就没有看懂,就是 TextView(getContext(), null, android.R.attr.listSeparatorTextViewStyle)这个构造函数,后来查了一下开发文档, 看了他的父类view的构造函数View (Context context, AttributeSet attrs, int defStyle) 发现defStyle参数的意思是这个view默认的风格,它可以是一个属性资源,这个属性的值可以在当前的theme里面获取到,或者它可以直接是一个显示定义的style资源。当前的theme又是什么呢? 其实它就是传进来的第一个参数context对象的Theme,具体到Settings里面,就是Settings这个Activity当前的Theme。在Settings这个应用的AndroidManufest.xml文件里可以看到,application标签里面有android:theme="android:Style/Theme.Holo",这就表示Settings应用里面的所有activity都将用到这个theme,也就是说settings这个activity的当前theme就是theme.holo,在framework/base/core/res/res/values/Themes.xml文件里面我找到了这个theme.holo。他的其中一项就是listSeparatorTextViewStyle,值为@android:style/widget.Holo.TextView.ListSeparator。这个值就是在TextView构造函数里要赋给android.R.attr.listSeparatorTextViewStyle属性的值,所以我最终目标的就是要改这个值了,哈哈,离胜利不远了!

    这个值是引用的一个style,所以我只需要把这个style改一下就OK了,首先找到这个style,它在framework/base/core/res/res/values/styles.xml 里面,可以看到他继承了Widget.TextView.ListSeparator这个style,并且override了两个属性。一个是background,一个是textAllCaps。到这里我也突然明白了,为什么标题栏的单词每个字母都是大写的,就是因为这里textAllCaps被赋值为true了!同事要改的是背景色,所以我这里只要修改一下background就可以了!如果还想改其他属性,只要在这里override一下就好了,嘿嘿,大功告成了!

setBackgroundResource 刷新 setting background_标题栏

    可能有人找不到哪里是“小标题栏”,我这里附上图片,就是下图蓝色小字“WIRELESS&NETWORKS”“DEVICE”所在的这一行,英文里面叫做category,直译就是种类,类别,就是说它下面的菜单项都属于这个类别。感觉直译不太好听,所以就很直观的取名叫小标题栏。

setBackgroundResource 刷新 setting background_xml_02

setBackgroundResource 刷新 setting background_xml_03