PreferenceFragment去完成设置页面
大多数时候我们都是这样去使用SharedPreferences
SharedPreferences sharedPreferences = getSharedPreferences("eric", Context.MODE_PRIVATE); //私有数据
Editor editor = sharedPreferences.edit();//获取编辑器
editor.putString("name", "eric");
editor.putInt("age", 4);
editor.commit();//提交修改
在app设置页面的开发中也会用到对设置项的保存,我们也会用到SharedPreferences去保存这些设置项,Android官方提供了更为简单针对设置页面使用SharedPreferences方法,那就是PreferenceActivity和PreferenceFragment. 下面来说下如何使用.
PreferenceActivity主要针对3.0以前的版本,PreferenceFragment则更为灵活,其实使用方法上面两者大致一样,所以PreferenceActivity就不展开讲解,直接来看PreferenceFragment的使用
一般来说Fragment会要求去关联一个布局的layout, 但是在PreferenceFragment则不需要这样做,我们需要去自定义一个xml加入首选项(首选项就是配置项,官方称为首选项). xml根节点必须是一个PreferenceScreen元素. PreferenceScreen里面的子项都作为一个独立的控件显示在界面里,同时还具备保存属性.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="checkbox_preference"
android:title="@string/title_checkbox_preference"
android:summary="@string/summary_checkbox_preference" />
<ListPreference
android:key="list_preference"
android:title="@string/title_list_preference"
android:summary="@string/summary_list_preference"
android:entries="@array/entries_list_preference"
android:entryValues="@array/entryvalues_list_preference"
android:dialogTitle="@string/dialog_title_list_preference" />
</PreferenceScreen>
显示效果如下
image.png
以上只展示了CheckBoxPreference和ListPreference,还有其它很多Preference控件,具体可以查阅官方文档有关Preference的字类.
如果设置项目过多,我们可以进行分类展示,有如下两种方式可以来实现.
使用标题
加入PreferenceCategory的属性可以进行标题的划分.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/inline_preferences">
<CheckBoxPreference
android:key="checkbox_preference"
android:summary="@string/summary_checkbox_preference"
android:title="@string/title_checkbox_preference"/>
</PreferenceCategory>
<PreferenceCategory
android:title="@string/inline_preferences">
<CheckBoxPreference
android:key="checkbox_preference"
android:summary="@string/summary_checkbox_preference"
android:title="@string/title_checkbox_preference"/>
<ListPreference
android:dialogTitle="@string/dialog_title_list_preference"
android:entries="@array/entries_list_preference"
android:entryValues="@array/entryvalues_list_preference"
android:key="list_preference"
android:summary="@string/summary_list_preference"
android:title="@string/title_list_preference"/>
</PreferenceCategory>
</PreferenceScreen>
使用子屏幕
使用PreferenceCategory属性可以划分子屏幕
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="@string/inline_preferences">
<CheckBoxPreference
android:key="checkbox_preference"
android:summary="@string/summary_checkbox_preference"
android:title="@string/title_checkbox_preference"/>
</PreferenceCategory>
<PreferenceScreen
android:key="button_voicemail_category_key"
android:title="Voice mail"
android:persistent="false">
<CheckBoxPreference
android:key="checkbox_preference"
android:summary="@string/summary_checkbox_preference"
android:title="@string/title_checkbox_preference"/>
<ListPreference
android:dialogTitle="@string/dialog_title_list_preference"
android:entries="@array/entries_list_preference"
android:entryValues="@array/entryvalues_list_preference"
android:key="list_preference"
android:summary="@string/summary_list_preference"
android:title="@string/title_list_preference"/>
</PreferenceScreen>
</PreferenceScreen>
配置intent跳转相应的activity
有时候我们的设置项目并不是保存一个配置项,而是去跳转到一个新的画面. 我们可以使用如下配置来使得首选项跳转一个网页
<Preference android:title="@string/prefs_web_page" >
<intent android:action="android.intent.action.VIEW"
android:data="http://www.example.com" />
</Preference>
当然你也可以配置显式的intent进行跳转,具体可以参见官方文档.
可以设置默认值给Preference控件
<!-- default value is a boolean -->
<CheckBoxPreference
android:defaultValue="true"
... />
<!-- default value is a string -->
<ListPreference
android:defaultValue="@string/pref_syncConnectionTypes_default"
... />
在进入设置页面可以调用
PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
对默认值进行初始化应用, 这个接口最常用的地方就是去恢复设置.
使用首选项标头
通常还有种需求是点击一个首选项跳转到另外一个屏幕,当然这个功能也可以通过PreferenceScreen来完成,但是使用PreferenceScreen不能兼容平板的情况就像下面这样
image.png
如果要实现这种效果就要使用到hearders
<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<header
android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
android:title="@string/prefs_category_one"
android:summary="@string/prefs_summ_category_one" />
<header
android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
android:title="@string/prefs_category_two"
android:summary="@string/prefs_summ_category_two" >
<!-- key/value pairs can be included as arguments for the fragment. -->
<extra android:name="someKey" android:value="someHeaderValue" />
</header>
</preference-headers>
android:fragment用来标记点击后跳转的Fragment,extra用来传递参数,可以在Fragment中通过getArguments()来获取传递过来的bundle数据, 这个数据最大的作用就是用来在同一个preference fragment中加载不同的preference xml.
public static class SettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String settings = getArguments().getString("settings");
if ("notifications".equals(settings)) {
addPreferencesFromResource(R.xml.settings_wifi);
} else if ("sync".equals(settings)) {
addPreferencesFromResource(R.xml.settings_sync);
}
}
}
如果要显示这个标头文件的内容需要去重写onBuildHeaders方法.
public class SettingsActivity extends PreferenceActivity {
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
}
preference-headers这个标签只能支持3.0以后的版本,如果要兼容3.0以前的版本需要另外在写个xml作为兼容
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:title="@string/prefs_category_one"
android:summary="@string/prefs_summ_category_one" >
<intent
android:targetPackage="com.example.prefs"
android:targetClass="com.example.prefs.SettingsActivity"
android:action="com.example.prefs.PREFS_ONE" />
</Preference>
<Preference
android:title="@string/prefs_category_two"
android:summary="@string/prefs_summ_category_two" >
<intent
android:targetPackage="com.example.prefs"
android:targetClass="com.example.prefs.SettingsActivity"
android:action="com.example.prefs.PREFS_TWO" />
</Preference>
</PreferenceScreen>
再以如下方式加载
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
// Load the legacy preferences headers
addPreferencesFromResource(R.xml.preference_headers_legacy);
}
}
// Called only on Honeycomb and later
@Override
public void onBuildHeaders(List<Header> target) {
loadHeadersFromResource(R.xml.preference_headers, target);
}
onBuildHeaders这个回调只会在Build.VERSION_CODES.HONEYCOMB(3.0系统)以上的版本调用。
另外我们必须要注意的一点,目前首选项不会再您调用registerOnSharedPreferenceChangeListener()时存储对监听器的强引用。但是,您必须存储对监听器的强引用,否则它将很容易被当作垃圾回收。
上面就是关于如何使用系统提供具有Preference功能的UI控件来打造一个设置界面. 更多详细关于自定义Preference等可以参考官方文档 https://developer.android.com/guide/topics/ui/settings