其中在介绍到Android的Sub Setting时,我们说到基本上都是使用的PreferenceFragment技术,今天我们就来了解一下关于PreferenceFragment相关的技术吧。
PreferenceFragment简述:
当我们在开发Android项目时一般都会用到首选项设置,在Android3.0之前我们都使用PreferenceActivity类来进行操作,这些设置习惯会被Preference自动保存下来,以便下次进入后恢复上一次的选择状态。
PreferenceActivity和普通的Activity不同,他们不使用setContentView加载布局,而是加载选项设置布局,而选择设置布局是以PreferenceScreen作为根元素的xml布局文件。
但在Android3.0之后Google不推荐我们使用PreferenceActivity来进行首选项设置,而是替换成了PreferenceFragment,其实二者的用法类似,只不过PreferenceFragment更容易扩展,所以推荐使用PreferenceFragment进行首选项设置。
PreferenceFragment是直接继承自Fragment,另选项布局xml文件的根节点一定是<PreferenceScreen>,在这个元素中我们可以添加不同的Preference,常用的Preference控件如下:
CheckBoxPreference、SwitchPreference、EditTextPreference、ListPreference、MultiSelectListPreference、
PreferenceCategory等。
接下来我们将通过分析一个Demo来了解PreferenceFragment吧。
首先来看应用的主界面:
以上为本次Demo的主界面,接下来将对每个选项的代码进行分析。
先建一个PrefFragment类继承自PreferenceFragment然后加载首选项配置的xml文件preferences.xml
public class PrefFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
//重写的以下方法请看后面讲解
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if ("select_linkage".equals(preference.getKey())) {
CheckBoxPreference checkBox = (CheckBoxPreference) findPreference("select_linkage");
ListPreference editBox = (ListPreference) findPreference("select_city");
editBox.setEnabled(checkBox.isChecked());
}
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
}
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(android.R.id.content, new PrefFragment()).commit();
}
}
运行后,会在/data/data/
另可通getPreferenceManager().setSharedPreferenceName()方法来设置文件的名称。
所有的控件都需要合入android:key属性,不然无法保存结果状态,android:title是大标题,android:summary是小标题。
(2)我们接着往下分析:
这段代码中包含很多控件,其中EditTextPreference是文本框选项,可以用来手动输入文字,android:dialogTitle属性用来设置对话框的标题内容,点击的效果图如下:
然后ListPreference是单选的列表选项,其中android:entries和android:entryValues需要指定数组作为值,
二者的区别在于android:entries中的值是供用户查看和选择的(即展示在界面上),
而android:entryValues的值是真正存储到手机中的值,我们在看下引入为entries和entryValues的值的cities数组。
- 南京
- 北京
- 上海
- 杭州
- 合肥
最后的运行效果图如下:
接下来分析MultiSelectListPreference控件,这是一个多选的列表选项,和单选的唯一区别就是可以进行多项选择,
效果图如下:
最后我们分析一下RingtonePreference和<PreferenceScreen>中的Intent,RingtonePreference是一个铃声选项,
可以加载手机中的铃声和短音,并做相应的处理。
而<PreferenceScreen>中的Intent加载链接、拨打电话、发送短信等等,只要有对应的Intent的,都可以进行操作。
(3)我们在接着往下分析:
<PreferenceCategory>中包含一个<PreferenceScreen>,通过这样的关系可以打开一个新的页面,
并且里面同时包含两个CheckBoxPreference控件,其中android:defaultValue是设置默认是否选择,
效果图如下:
这是一个新开的页面,里面只包含两个CheckBoxPreference控件,并且通过android:summaryOn
和android:summaryOff属性控制选择与否的差别。
(4)最后着重分析一下onPreferenceTreeClick()监听事件:
运行的效果图如下:
当选中是否联动的CheckBoxPreference时,下面的ListPreference可使用,但当不选择CheckBoxPreference时,ListPreference将变成灰色无法被选中。
控制这段逻辑的代码在之前提到的Fragment中就已体现,这里单独拉出来分析一下:
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if ("select_linkage".equals(preference.getKey())) {
CheckBoxPreference checkBox = (CheckBoxPreference) findPreference("select_linkage");
ListPreference editBox = (ListPreference) findPreference("select_city");
editBox.setEnabled(checkBox.isChecked());
}
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
当任意的Preference控件被点击时,都会触发onPreferenceTreeClick这个方法回调,且通过preference.getKey()这个方法可以定位到哪个控件进行了操作,最终通过editBox.setEnabled(checkBox.isChecked());将CheckBox和ListPreference进行了绑定。
到这里PreferenceFragment的分析也就告一段落了,经过之前的分析大家也应该了解到这个类的优点在哪里,平时我们在做自己的项目时,遇到类似于这样的设置属性时,无需一个一个控件去慢慢布局了,而且那样处理逻辑时比这种方式复杂太多了。所以以后遇到类似的问题还是使用这种方式处理更加方便。