此包下的类主要以Preference为父类,PreferenceActivity继承自ListActivity用来显示UI,以ListView形式显示,preference主要用来做配置文件,所做的选择以Sharedpreference(xml)形式存于程序目录下。
使用方式:定义一个xml(随便放哪,最好在res下建个xml文件夹,放里面)文件,在java代码中addPreferencesFromResource(int res),最基本的preference就完成了。
也可以
PreferenceManager pm = getPreferenceManager(); PreferenceScreen screen = pm.createPreferenceScreen(this); setPreferenceScreen(screen);设置根View。
xml文件内以PreferenceScreen作为根节点,比如:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <ListPreference android:entryValues="@array/r" android:entries="@array/r" android:title="qqqqqqqq" android:summary="wwwwwwwwww" android:dialogTitle="hhh" android:key="55"/> <CheckBoxPreference /> </PreferenceScreen>
Preference :所有preference的父类,其属性子类继承
XML属性:
android:key 用于存储、取出数据的key。
android:title 用于显示的标题,标题在上面一行,最多有两行。
android:summary 摘要,配置的简要说明,显示在标题下面
android:selectable 是否能点取选择,设置false则此条preference不可选(lose focus)
android:enabled 是否起作用,false则能点取,但是不作用(有焦点)
android:shouldDisableView 当enabled设置为false,此属性设置为true时,preference所代表的item变暗
android:layout 自定义item的View
DialogPreference:弹dialog的preference的父类,不直接在XML文件中定义,而用其子类。继承自Preference
android:dialogIcon 弹出的dialog的图标
android:dialogMessage dialog的消息
android:dialogTitle dialog的标题
android:negativeButtonText dialog的取消按钮上面的文字
android:positiveButtonText dialog的确定按钮上的文字
android:dialogLayout 自定义dialog布局
ListPreference:点击后弹dialog,dialog内是个单选ListView。继承自DialogPreference
XML属性:
android:entries 用于显示的数组,弹出来的Dialog中ListView所显示的内容
android:entryValues 被选取后所得到的数据,数组,对应entries。
不能设置dialogMessage,否则ListView将被Message内容覆盖。
EditTextPreference:点击后弹dialog,dialog的View部分是个EditText。继承自DialogPreference
XML属性:没有独有属性
TwoStatePreference:代表两种状态转换的配置类,不直接用,而用其子类
XML属性:没有独有属性
CheckBoxPreference: 带checkbox的item,点击后checkbox状态改变。4.0继承自TwoStatePreference,2.3继承自Preference
XML属性:
android:summaryOff 当checkbox状态为false时,显示的摘要内容
android:summaryOn 当checkbox状态为true时,显示的摘要内容
PreferenceCategory:对preference进行分组。
XML属性:没有独有属性
源码分析:
当点击Preference的Item时,首先触发方法:performClick(PreferenceScreen preferenceScreen)
void performClick(PreferenceScreen preferenceScreen) { if (!isEnabled()) { return; } onClick(); if (mOnClickListener != null && mOnClickListener.onPreferenceClick(this)) { return; } PreferenceManager preferenceManager = getPreferenceManager(); if (preferenceManager != null) { PreferenceManager.OnPreferenceTreeClickListener listener = preferenceManager .getOnPreferenceTreeClickListener(); if (preferenceScreen != null && listener != null && listener.onPreferenceTreeClick(preferenceScreen, this)) { return; } } if (mIntent != null) { Context context = getContext(); context.startActivity(mIntent); } }很明显,如果设置了setEnable(false),后面所有代码都失去作用了。
if (mOnClickListener != null && mOnClickListener.onPreferenceClick(this)) { return; }下面一段代码决定了点击后跳转到另一个Activity。
if (mIntent != null) { Context context = getContext(); context.startActivity(mIntent); }其中mIntent可通过setIntent(Intent intent)方法设定,也可在布局文件中如下设定
<Preference android:title="@string/ua_settings" > <intent android:action="android.intent.action.webview" android:targetClass="com.yeezone.engtest.Uaagent" android:targetPackage="com.yeezone.engtest" /> </Preference>
源码版本2.3:
CheckboxPreference:
实现父类Preference的onclick方法:
@Override protected void onClick() { super.onClick(); boolean newValue = !isChecked(); // in onBindView() an AccessibilityEventViewClickedType is sent to announce the change // not sending mSendAccessibilityEventViewClickedType = true; if (!callChangeListener(newValue)) { return; } setChecked(newValue); }其中callChangeListener(newValue)方法代码如下:
protected boolean callChangeListener(Object newValue) { return mOnChangeListener == null ? true : mOnChangeListener.onPreferenceChange(this, newValue); }上面这个方法中可以看出,如果对这个Preference进行了Preference.OnPreferenceChangeListener监听,并且监听的返回值为true那么后面的代码将不会再执行。
setChecked(newValue)方法会把newValue存到配置文件中去。
DialogPreference:不直接使用,而是作为父类使用
实现父类Preference的onclick方法:
@Override protected void onClick() { showDialog(null); }其中showDialog方法主要用来构建并显示一个AlertDialog,并且调用onPrepareDialogBuilder(mBuilder);方法,并且对Dialog实现dissmiss监听,在onDismiss方法中调用方法onDialogClosed(mWhichButtonClicked == DialogInterface.BUTTON_POSITIVE);,onPrepareDialogBuilder与onDialogClosed是空方法,留给子类实现。showDialog代码如下:
protected void showDialog(Bundle state) { Context context = getContext(); mWhichButtonClicked = DialogInterface.BUTTON_NEGATIVE; mBuilder = new AlertDialog.Builder(context) .setTitle(mDialogTitle) .setIcon(mDialogIcon) .setPositiveButton(mPositiveButtonText, this) .setNegativeButton(mNegativeButtonText, this); View contentView = onCreateDialogView(); if (contentView != null) { onBindDialogView(contentView); mBuilder.setView(contentView); } else { mBuilder.setMessage(mDialogMessage); } onPrepareDialogBuilder(mBuilder); getPreferenceManager().registerOnActivityDestroyListener(this); // Create the dialog final Dialog dialog = mDialog = mBuilder.create(); if (state != null) { dialog.onRestoreInstanceState(state); } if (needInputMethod()) { requestInputMethod(dialog); } dialog.setOnDismissListener(this); dialog.show(); }从上面代码中可以看出,如果 View contentView = onCreateDialogView();得到的contentView 是个null则Dialog为一个简短消息的Dialog,不为null还是个简短消息的Dialog,不过样式不同了。可继承DialogPreference,重写onCreateDialogView()方法来达到控制Dialog显示的目的。
protected View onCreateDialogView() { if (mDialogLayoutResId == 0) { return null; } LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE); return inflater.inflate(mDialogLayoutResId, null); }
EditTextPreference:继承DialogPreference
重写了onPrepareDialogBuilder(mBuilder)方法,把Dialog的View部分变成了一个EditText。没有从写onPrepareDialogBuilder(mBuilder)方法,重写了onDialogClosed方法,代码如下:
@Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); if (positiveResult) { String value = mEditText.getText().toString(); if (callChangeListener(value)) { setText(value); } } }从上面的代码可以看出,此方法被调时,如果参数 是true并且callChangeListener(value)返回true,则保存变化的值到配置文件中,当且仅当点击了确定按钮时才会传true。callChangeListener方法说明在CheckboxPreference部分。
重写了onPrepareDialogBuilder与onDialogClosed方法,onPrepareDialogBuilder代码如下:
@Override protected void onPrepareDialogBuilder(Builder builder) { super.onPrepareDialogBuilder(builder); if (mEntries == null || mEntryValues == null) { throw new IllegalStateException( "ListPreference requires an entries array and an entryValues array."); } mClickedDialogEntryIndex = getValueIndex(); builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { mClickedDialogEntryIndex = which; /* * Clicking on an item simulates the positive button * click, and dismisses the dialog. */ ListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE); dialog.dismiss(); } }); /* * The typical interaction for list-based dialogs is to have * click-on-an-item dismiss the dialog instead of the user having to * press 'Ok'. */ builder.setPositiveButton(null, null); }代码比较容易懂。
onDialogClosed代码如下:
@Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); if (positiveResult && mClickedDialogEntryIndex >= 0 && mEntryValues != null) { String value = mEntryValues[mClickedDialogEntryIndex].toString(); if (callChangeListener(value)) { setValue(value); } } }