初学者Android4.0 Settings分析(一)

菜鸟Android4.0 Settings分析(一)

先声明:本人工作半年,是真的菜鸟,之前有做过2.3的Launcher,没有记录下来,感觉挺可惜的,现在老大叫我搞Setting,我觉得是得写得东西,记录下自己的工作。设备都还没到,现在只能看看代码,就先记录下看代码的收获吧。。


注意:Fragment是android3.0以上才支持的,3.0之前得导jar包,我在找Setting里面ListView的item的click事件时找了好久,因为之前关联的是2.3的源码,当我跳到PreferenceActivity类里面想看下Header类里,一直找不到(sb了),最后到官方的Reference上去找才想起来自己的源码关联的是2.3的(真的sb了...)。。。

Settings的包结构:

初学者Android4.0 Settings分析(一)

 一、Setting的主界面

public class Settings extends PreferenceActivity implementsButtonBarHandler

1、布局
4.0的Setting是采用PreferenceFragment的形式进行布局的。

它的布局文件是xml文件夹下的:settings_headers.xml

这个布局文件下面全是<Header></Header>标签,e.g:
<header android:title="@string/header_category_wireless_networks" />
这个代表的界面就是:
初学者Android4.0 Settings分析(一)
设置界面最上面的一个分类(category)

2、com.android.settings.Settings.java主activity

实现onBuildHeaders()回调用来指定头文件,即加载界面对应的Fragment
调用loadHeadersFromResource()方法对界面进行加载
@Override
public void onBuildHeaders(List<Header> headers) {
    loadHeadersFromResource(R.xml.settings_headers, headers);
    updateHeaderList(headers);
    mHeaders = headers;
}

Ctrl+T查看下Settings的继承关系
Settings-->PreferenceActivity-->ListActivity-->Activity-->xxx
可以看到Settings是ListActivity的一个后代,可知Setting主界面的项都是放在一个ListView里面的
查看一下Settings的代码发现:
@Override
    public void setListAdapter(ListAdapter adapter) {
    	if (mHeaders == null) {
    		mHeaders = new ArrayList<Header>();
    		// When the saved state provides the list of headers, onBuildHeaders is not called
    		// Copy the list of Headers from the adapter, preserving their order
    		for (int i = 0; i < adapter.getCount(); i++) {
    			mHeaders.add((Header) adapter.getItem(i));
    		}
    	}
    	// Ignore the adapter provided by PreferenceActivity and substitute ours instead
    	super.setListAdapter(new HeaderAdapter(this, mHeaders));
    }






所以这个才是显示界面的地方。其中HeaderAdapter是Settings中的一个内部类。下面来看下HeaderAdapter这个适配类
private static class HeaderAdapter extends ArrayAdapter<Header> {
    	//三种 类型的header
    	static final int HEADER_TYPE_CATEGORY = 0;//分类
    	static final int HEADER_TYPE_NORMAL = 1;//一般的
    	static final int HEADER_TYPE_SWITCH = 2;//开关形式的
    	....
    }

类的开头就定义了三个常量:这个代表Header的三种类型
HEADER_TYPE_CATEGORY代表一个分类,它不能点击,像这个:
初学者Android4.0 Settings分析(一)
HEADER_TYPE_NORMAL代表一个常规项,像这个:
初学者Android4.0 Settings分析(一)
HEADER_TYPE_SWITCH代表一种开头形式的类型,像这个:
初学者Android4.0 Settings分析(一)

getView()方法中也是根据三种不同的类型,加载不同的view以及数据。

显示基本上就这样了,下面就是事件的响应了,点击一个item后的响应。查看一下PreferenceActivity的源码,可以看到PreferenceActivity重写了ListActivity的这个文法
@Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
    	super.onListItemClick(l, v, position, id);
    	if (mAdapter != null) {
    		Object item = mAdapter.getItem(position);
    		if (item instanceof Header) onHeaderClick((Header) item, position);
    	}
    }

再看onHeaderClick()方法
public void onHeaderClick(Header header, int position) {
		if (header.fragment != null) {
			if (mSinglePane) {
				int titleRes = header.breadCrumbTitleRes;
				int shortTitleRes = header.breadCrumbShortTitleRes;
				if (titleRes == 0) {
					titleRes = header.titleRes;
					shortTitleRes = 0;
				}
				startWithFragment(header.fragment, header.fragmentArguments,
						null, 0, titleRes, shortTitleRes);
			} else {
				switchToHeader(header);
			}
		} else if (header.intent != null) {
			startActivity(header.intent);
		}
	}


今天就到这里,明天继续。。。。