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. Android Framework------之ActivityManagerService与Activity之间的通信

    研究Android系统的童鞋,想必都已经了解一个Activity的启动过程了.而且在网上,关于Activity的启动的文章非常多,很容易就能找到的.这篇文章的重点放在ActivityManagerSe ...

  2. [POJ] 3020 Antenna Placement(二分图最大匹配)

    题目地址:http://poj.org/problem?id=3020 输入一个字符矩阵,'*'可行,'o'不可行.因为一个点可以和上下左右四个方向的一个可行点组成一个集合,所以对图进行黑白染色(每个 ...

  3. d3可视化实战00:d3的使用心得和学习资料汇总

    最近以来,我使用d3进行我的可视化工具的开发已经3个月了,同时也兼用其他一些图表类库,自我感觉稍微有点心得.之前我也写过相关文章,我涉及的数据可视化的实现技术和工具,但是那篇文章对于项目开发而言太浅了 ...

  4. 转:VC中MessageBox的常见用法

    一.关于MessageBox       消息框是个很常用的控件,属性比较多,本文列出了它的一些常用方法,及指出了它的一些应用场合.       1.MessageBox("这是一个最简单的 ...

  5. [布局] bootstrap基本标签总结

    文件头: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <titl ...

  6. Linux服务器间信任关系建立方法

    http://blog.csdn.net/jiangzeyun/article/details/42489359

  7. ural 1294 Mars Satellites

    #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> u ...

  8. 两段小PYTHON,作啥用的,行内人才懂~~~:(

    哎,作也不是,不作也不是.... 下次有更新文件时,直接刷新一次了. #coding: UTF-8 import sys reload(sys) sys.setdefaultencoding( &qu ...

  9. bootstrap栅格布局,第一次成功

    代码: <div class="helper" style="background-color: #F7F7F9;height: 200px;padding-top ...

  10. iOS开发手记 - iOS9.3 Xcode7打包ipa文件在其他越狱机器上运行的方法和一些问题

    现在Xcode7可以用一个appleid就可以往手机上部署测试app,不再需要$99,这也是方便.但是要把app发给别人的手机上运行还是不行,除非别人的手机在你身边可以直接通过Xcode安装 关于怎么 ...