首选项框架PreferenceFragment部分源码分析

因为要改一些settings里面的bug以及之前在里面有做过勿扰模式,准备对勿扰模式做一个总结,那先分析一下settings的源码,里面的核心应该就是android3.0 上面的首选项框架PreferenceFragment。因为在3.0之前都是把这些东西放在PreferenceActivity的,但是3.0之后google建议把setting放在PreferenceFragment,但是PreferenceActivity也同时在用的,下面就此总结一下:

PreferenceActivity的作用是管理所有headers,而每一个header对应一个PreferenceFragment,对应不同的设置种类界面所以我感觉PreferenceActivity偏向系统级的设置,就比如android系统的settings,对于一些简单的应用设置一个PreferenceFragment是可以搞定的。

我们自定义一个activity extends PreferenceActivity必须重写onBuildHeaders()这个方法,在这里加载一个xml布局显示:

@Overridepublic void onBuildHeaders(List<Header> target) {// TODO Auto-generated method stubloadHeadersFromResource(R.xml.activity_headers, target);}自己写一个xml文件看下,R.xml.activity_headers:

<?xml version="1.0" encoding="utf-8"?><preference-headers xmlns:android="" ><headerandroid:id="@+id/wifi"android:title="wifi"android:icon="@drawable/ic_launcher"android:fragment="com.example.preferencefragmenttest.WifiFragment"/><headerandroid:id="@+id/net"android:title="移动网络"android:icon="@drawable/ic_launcher"android:fragment="com.example.preferencefragmenttest.NetFragment"/><headerandroid:id="@+id/ee"android:title="打开activity"android:icon="@drawable/ic_launcher"><intent android:action="android.intent.action.NEW"></intent></header></preference-headers>每一个header点击就会进入一个新的界面,有两种情况:要么是fragment要么是intent打开一个activity,先看看源码了解这里的原理,为什么点击就会进入相应界面,找到父类PreferenceActivity有个方法:

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);}} 很明显可以看出它判断了header对应fragment和activity的两种情况,打开activity这个好理解,看看fragment是怎么打开的,进入switchToHeader(),再进去switchToHeaderInner():

private void switchToHeaderInner(String fragmentName, Bundle args, int direction) {getFragmentManager().popBackStack(BACK_STACK_PREFS,FragmentManager.POP_BACK_STACK_INCLUSIVE);if (!isValidFragment(fragmentName)) {throw new IllegalArgumentException("Invalid fragment for this activity: "+ fragmentName);}Fragment f = Fragment.instantiate(this, fragmentName, args);FragmentTransaction transaction = getFragmentManager().beginTransaction();transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);transaction.replace(com.android.internal.R.id.prefs, f);transaction.commitAllowingStateLoss();} 很明确的知道这个跳转的fragment被装载在当前的activity了,也是告诉我们不需要再new 自己的activity来装这个fragment,我们只需要在header里面写好fragment的属性。那么为啥有的header还是用intent指定activity呢。我分析是因为有些系统界面需要别的应用直接intent访问,比如WIFI设置界面:

startActivity(new Intent( android.provider.Settings.ACTION_WIRELESS_SETTINGS)); 那当然需要想自己再建一个activity了,,接着就是PreferenceFragment的用法,也是自定义fragment extendsPreferenceFragment,并且加载xml布局:

@Overridepublic void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);addPreferencesFromResource(R.xml.wifi_preference);}看一下这个布局,简单的写几个系统自带的preference:

<?xml version="1.0" encoding="utf-8"?><PreferenceScreen xmlns:android=""><CheckBoxPreferenceandroid:key="isopen"android:title="wifi"android:defaultValue="true"/><ListPreferenceandroid:key="list"android:title="声音大小"android:entries="@array/keys"android:entryValues="@array/values"/><Preferenceandroid:key="click"android:title="单独的"/></PreferenceScreen> 还可以在里面加入PreferenceCategory标签,作用是分块吧,中间间隔稍微大一些,区分同一页面不同设置类别

灿烂甜美!那一瞬的激-情绽放,催人奋进!胜利,永远属于为梦想奋斗的人新乐吧

首选项框架PreferenceFragment部分源码分析

相关文章:

你感兴趣的文章:

标签云: