1. Preference Header 概述:

对于什么是 Preference Header,以及何时使用 Preference Header,请参考我的另一篇博文: 何时使用 Preference Headers
2. 自定义 Preference Header 布局的必要性:
Preference Header 的设计初衷是作为复杂设置选项的一个简单抽象或者概括,所以它本身应该一目了然,让用户一看便知道下一级设置中大概都有哪些设置选项,在布局设计上也应简单,所以谷歌给 header 统一只设置了 icon、title 和 summary 三个布局项。

基于以上原则,谷歌并没有给 Preference Header 提供方便的自定义接口,或许考虑到这本身不需要做什么自定义。但是有时候我们确实需要做一些简单的自定义。比如,你的 APP 需要统一 UI 风格,需要自定义的字体、颜色、selector样式等,这时当你需要用到 Preference Header 的时候就需要考虑对其布局进行
微自定义。

3. 如何自定义?
在本文中,我们将实现对 Preference Header 布局的有限的自定义,实现如下图所示的效果,上图为没有自定义的效果,下图为自定义之后的效果:












3.1 寻找 Preference Headers 的布局方式:
Headers 是在 PreferenceActivity 中进行布局的,PreferenceActivity 其实是继承了一个 ListActivity,所以呈现在我们面前的 Headers 列表其实就是一个 ListView,那么我们很自然地想到每个 Header ,即每个 list item 的布局应该在一个 list adapter 中被 inflated ,查看 PreferenceActivity 的
源代码,
发现里面定义了一个 ArrayAdapter<Header> 的子类 HeaderAdapter,请注意 getView 中是如何 inflate header item 布局的:


@Override
public View getView(int position, View convertView, ViewGroup parent) {
HeaderViewHolder holder;
View view; if (convertView == null) {
view = mInflater.inflate(com.android.internal.R.layout.preference_header_item,
parent, false);
holder = new HeaderViewHolder();
holder.icon = (ImageView) view.findViewById(com.android.internal.R.id.icon);
holder.title = (TextView) view.findViewById(com.android.internal.R.id.title);
holder.summary = (TextView) view.findViewById(com.android.internal.R.id.summary);
view.setTag(holder);
} else {
view = convertView;
holder = (HeaderViewHolder) view.getTag();
} ......
return view;
}
3.2 分析 header item 布局文件 preference_header_item.xml :
从 getView 方法中我们确认了 header item 的布局在 preference_header_item.xml 这个文件中,那么要更改布局方式其实就是修改这个文件,我们从源码的资源文件中找到该文件的 
源代码,
发现每一个 header item 都由 icon(ImageView)、title(TextView) 和 summary(TextView) 三个元素组成。接下来就可以考虑如何对其进行修改了。


3.3 如何修改 preference_header_item.xml?
这里我们不打算对 header 进行复杂的自定义(比如,增加额外的 header 元素,这个需要对 Header 本身也进行定制,考虑到 Header 的简洁要求,个人觉得没有必要这么做)。

在本文中,我们实现一些比较有用的自定义,具体来说包括如下修改: icon 和 title、summary 位置的互换,title 和 summary 字体颜色、大小的更改,list item 高度的修改,list item 背景的修改(修改 selector),正如上图给出的效果所示。

3.4 定义一个本地布局文件 custom_preference_header_item.xml:
我们将原生的 preference_header_item.xml 文件拷贝到本地工程 layout 文件夹中,修改文件名称为 custom_preference_header_item.xml,并对布局进行 3.3 中所述的修改。

3.5 定义一个 PreferenceActivity 的子类 CustomPreferenceActivity:
在 CustomPreferenceActivity 中重新定义一个 HeaderAdapter,主要将其中的


view = mInflater.inflate(com.android.internal.R.layout.preference_header_item,
parent, false);
修改为:

view = mInflater.inflate(R.layout.custom_preference_header_item,
parent, false);
由于 PreferenceActivity 中的 List<Header> 成员 mHeaders 是私有的,而我们要将 mHeaders 作为数据源参数传递给新定义的 HeaderAdapter 中,为了解决这个问题,我们在 CustomPreferenceActivity 中再定义一个 List<Header> 成员 mCopyHeaders,作为 mHeaders 的一个拷贝,并通过重写 loadHeadersFromResource 方法将 mHeaders 赋值给 mCopyHeaders:

     @Override
public void loadHeadersFromResource(int resid, List<Header> target) {
super.loadHeadersFromResource(resid, target);
mCopyHeaders = target;
}
注意:
loadHeadersFromResource
 中的 target 参数即为 mHeaders,详细请参考 PreferenceActivity 源码。

在 PreferenceActivity 源码 
中,setListAdapter() 是在 onCreate() 方法中调用的,为此,我们还要重写 onCreate() 方法,将 CustomPreferenceActivity 中的 adapter 设置为自定义的 HeaderAdapter 对象:

     @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); if (mCopyHeaders != null && mCopyHeaders.size() > 0) {
setListAdapter(new HeaderAdapter(this, mCopyHeaders));
}
}
至此,Preference Header 的自定义布局就完成了,接下来就只需要定义一个 CutomPreferenceActivity 的子类,并编写相应的 preference-headers 文件,重新 onBuildHeaders() 方法就可以了:

     @Override
public void onBuildHeaders(List<Header> target) {
this.loadHeadersFromResource(R.xml.preference_headers, target);
}
完整的工程请下载:CustomPreferenceHeader




自定义 Preference Header 布局的更多相关文章

  1. Android设置选项开发及自定义Preference样式

    一个完整的Android应用程序都应该提供选项(或者叫偏好设置等等)让用户对APP的表现形式能够进行设置,比如说是否加入用户体验计划,或者是否自动升级.定时提醒.开启自启动.后台运行等等.提供一个好的 ...

  2. 自定义 Collection View 布局

    自定义 Collection View 布局 answer-huang 29 Mar 2014 分享文章 UICollectionView 在 iOS6 中第一次被引入,也是 UIKit 视图类中的一 ...

  3. iOS系列译文:自定义Collection View布局

    原文出处: Ole Begemann   译文出处: 黄爱武(@answer-huang).欢迎加入技术翻译小组. UICollectionView在iOS6中第一次被介绍,也是UIKit视图类中的一 ...

  4. 常用样式制作思路 自定义按钮~自适应布局~常见bug seajs简记 初学者必知的HTML规范 不容忽略的——CSS规范

    常用样式制作思路   学习常用样式总结参考来自这里 带点文字链接列表利用:before实现 1 <!DOCTYPE html> 2 <html lang="en" ...

  5. 自定义Collection View布局

    转自answer-huang的博客 原文出自:Custom Collection View Layouts    UICollectionView在iOS6中第一次被介绍,也是UIKit视图类中的一颗 ...

  6. Android动画效果之自定义ViewGroup添加布局动画

    前言: 前面几篇文章介绍了补间动画.逐帧动画.属性动画,大部分都是针对View来实现的动画,那么该如何为了一个ViewGroup添加动画呢?今天结合自定义ViewGroup来学习一下布局动画.本文将通 ...

  7. Android自定义Dialog及其布局

     实际项目开发中默认的Dialog样式无法满足需求,需要自定义Dialog及其布局,并响应布局中控件的事件. 上效果图: 自定义Dialog,LogoutDialog: 要将自定义布局传入构造函数中, ...

  8. iOS-AFNetworking封装Get(自定义HTTP Header)和Post请求及文件下载

    前面提到AFNetworking是一个很强大的网络三方库,首先你需要引入AFNetworking三方库:如封装的有误还请指出,谢谢! 1.Get请求 /**Get请求 url 服务器请求地址 succ ...

  9. Android中自定义Preference

    一.需求 开发横屏设备的app时,发现preference显示的都是上下结构,因此需要自定义preference实现横屏显示. 二.layout实现 <?xml version="1. ...

随机推荐

  1. Microsoft OLE DB Provider for SQL Server 错误 '80040e21'

    我的是因为数据库满了,正在向服务商申请增加数据库容量 原文地址:Microsoft OLE DB Provider for SQL Server 错误 '800作者:欧阳IT记事本 昨天打开网站还正常 ...

  2. Xcode-Xcode 7.3 解决不能自动联想问题-备

    一.问题: 升级Xcode 7.3 之后发现导入头文件之后,没法自动联想. 二. 解决办法: 打开Xcode --> Target --> BuildSettings --> App ...

  3. 高性能web

    http://developer.51cto.com/art/201104/255619.htm http://developer.51cto.com/art/201104/254031.htm ht ...

  4. 包含无数好东西的ownCloud

    ownCloud 是一个来自 KDE 社区开发的免费软件,提供私人的 Web 服务.当前主要功能包括文件管理(内建文件分享).音乐.日历.联系人等等,可在PC和服务器上运行. 简单来说就是一个基于Ph ...

  5. 关于标准C语言的预定义宏

    标准C语言预处理要求定义某些对象宏,每个预定义宏的名称一两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程人员重新定义.下面预定义宏表,被我抄了下来.__LINE__  当前 ...

  6. 【转】JAVA 读写二进制文件

    原文网址:http://shiminghua234.blog.163.com/blog/static/263912422011619102350866 import java.io.*; /** * ...

  7. java与数据结构(6)---java实现链栈

    栈之链式存储结构链栈 链栈 栈的链式存储结构成为链栈.链栈是没有头结点,头结点就是栈顶指针top. 代码结构 package list; public interface Stackable;公共接口 ...

  8. SecureCRT7.3和SecureFX7.3的MAC下破解

    破解脚本:http://files.cnblogs.com/files/jieyuefeng/SecureCRTFX_mac_crack.zip 破解方法: sudo perl ~/Downloads ...

  9. sublime3 使用技巧

    Ctrl+O(Command+O)可以实现头文件和源文件之间的快速切换 Ctrl+Shift+T可以打开之前关闭的tab页,这点同chrome是一样的 Ctrl+R定位函数:Ctrl+G定位到行: 插 ...

  10. Highcharts 带有数据标签曲线图表

    <html> <head> <meta charset="UTF-8" /> <title>Highcharts</title ...