前言
这几天在看书时,意外地看到了Preference框架。相对于IOS SDK,这个功能在创建设置界面时会更加容易一点。开发者只需要编辑一个简单的xml文件,
就能开发出一个简单的设置界面。我在网上找了一些资料,看到这些资料都只是简单的介绍了这个功能的使用,不够具体时间上也比较早。现在我就详细的介绍一下它的使用。
使用场景
在Android手机中都有设置功能,许多的android应用也有相应的设置界面允许用户修改应用特性和行为。在为这些应用提供设置 功能时,开发者应该使 Android的Preference API构建一个与其他Android应用中的用户体验一致的界面(包括系统设置)。
概览
设置是使用在XML文件中声明的 Preference 类的各种子类构建而成,而不是使用View对象构建用户界面。
Preference 对象是单个设置的构建基块。每个Preference都有一个相应的键值对,可供系统用来将设置保存在应用设置的默认SharedPreferences文件中。当用户更改设置时,系统会自动更新SharedPreferences文件中的相应值。开发者只应在需要读取值以根据用户设置确定应用的行为时,才与关联的 SharedPreferences文件直接交互。
保存在SharedPreferences中的值主要是以下数据类型:
1.布尔型
2.浮点型
3.整型
4.长整型
5.字符串
6.字符串 Set
同时,开发者还需要专门的Activity和Fragment子类来显示UI。在3.0之前的Android版本中,开发者必须使用继承PreferenceActivity的activity;在3.0及更高的版本中,开发者可以使用普通的activity,同时使用继承PreferenceFragment的Fragment。如果需要多组设置,则可以使用PreferenceActivity为大屏幕创建双窗格布局。
首选项
Preference 对象是单个设置的构建基块,而其他的应用设置都是Preference的子类表示。每个子类都可以指定标题和默认值等内容,同时也有自己特定的属性和用户界面。最常用的首选项如下:
CheckBoxPreference:CheckBoxPreference 可创建一个列表项用于显示复选框,显示一个包含已启用或已禁用设置复选框的项目。
ListPreference:ListPreference 可创建一个项目用于打开包含选择列表的对话框,打开一个包含单选按钮列表的对话框。保存的值可以是任一受支持的值类型。
EditTextPreference:打开一个包含 EditText 小工具的对话框。
DialogPreference:打开一个dialog对话框。
MultiSelectListPreference:打开一个包含多选按钮列表的对话框。
SwitchPreference:一个switch选择器。
使用 XML 定义首选项
开发者开始在运行时直接实例化新的Preference对象,但是一般情况下,还是应该在XML文件中定义设置列表。这样更容易阅读和查看。
XML文件必须保存在 res/xml/ 目录中。 XML文件中的根节点必须是
1 | <EditTextPreference |
在此示例中,两个项有3个共同的属性:
1.android:key:对于要保留数据值的首选项,必须拥有此属性。它指定系统在将此设置的值保存在 SharedPreferences 中时所用的唯一键(字符串)。
2.android:title:此属性为设置提供用户可见的名称。
3.android:summary:此属性为设置提供用户可见的概述。
使用设置组
如果开发者的设置列表中需要的设置选项比较多时,开发者可以使用设置组来进行分组,方便用户浏览、理解和处理设置。设置组可以有效的将一个长列表转化成多个段列表,方法有以下两种:
-
使用标题
以分隔线分隔两组设置并为其提供标题,将每组 Preference 对象放入 PreferenceCategory 内。
1 | <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> |
-
使用子屏幕
将设置或设置组放入到子屏幕,点击时会跳转到子屏幕显示。
1 | <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> |
使用 Intent 跳转
在特殊情况,应用需要在设置页面跳转到应用的其他页面。所以要在用户选择首选项时调用Intent,需要在相应的Preference元素中添加intent。添加的intent的可以分为隐式和显式。
1 | <Preference android:title="intent" > |
intent可以添加一下属性:
android:action:要分配的操作(按照 setAction() 方法)。
android:data:要分配的数据(按照 setData() 方法)。
android:mimeType:要分配的 MIME 类型(按照 setType() 方法)。
android:targetClass:组件名称的类部分(按照 setComponent() 方法)。
android:targetPackage:组件名称的软件包部分(按照 setComponent() 方法)。
创建首选项的 Activity 和 Fragment
在XML文件配置完成之后,要在Activity中显式设置,需要扩展PreferenceActivity类。该类会根据自动保留每个Preference相关的设置。
1 | public class SettingsActivity extends PreferenceActivity { |
在Android3.0及更高的版本中,应该使用PreferenceFragment来代替PreferenceActivity的使用。在PreferenceFragment中使用与在PreferenceActivity中使用基本一样。
1 | public static class SettingsFragment extends PreferenceFragment { |
同时需要在Activity中添加Fragment,代码如下:
1 | public class SettingsActivity extends Activity { |
设置默认值
在很多情况下,我们需要在用户第一次打开应用时就有默认值。所以需要对相应的Preference设置默认值。
设置默认值需要在XML文件中对Preference设置 android:defaultValue 属性。不同的 Preference 的默认值类型页不一样,比如CheckBoxPreference 的默认值是布尔值,而 ListPreference 的默认值类型是string。
然后需要在应用的主activity(设置为
1 | PreferenceManager.setDefaultValues(this,R.xml.main_activity,false); |
其中第三个参数表示是否多次设置默认值。如果第三个参数设置为false,则应用只有在第一次调用activity时会设置默认值,如果设置为true,则每次应用打开时都会将值设置为默认值。
使用首选项标头
在大显示屏尤其是pad情况下,我们应该使用标头功能,而不是使用嵌套功能。使用标头功能的好处是在大屏幕上,preferenceActivity会自动提供双窗口显示。如下图:
而在小屏幕中则与嵌套差不多。
使用标头构建设置的方法:
-
创建多个PreferenceFragment实例,每个实例都需要一个单独的XML文件。
-
创建XML标头文件,其中每个设置都要对应一个相应的fragment。
1 | <?xml version="1.0" encoding="utf-8"?> |
在元素中可以使用bundle传递其他参数,在片段中可以使用getArgument()来获取参数,从而根据不同的参数使用同一个fragment加载不同的xml文件。
-
将activity继承PreferenceActivity,并且实现onBuildHeaders()方法来显示标头,同时需要重写isValidFragment方法,对可以使用的fragment返回true。
1 | public class SettingsActivity extends PreferenceActivity { |
由于header是在android3.0之后添加的新功能,所以如果要兼容3.0之前的版本,我们需要在使用前文介绍的嵌套功能进行兼容。
activity主要的代码如下:
1 | @Override |
读取和监听首选项的变化
- 读取首选项
默认情况下,应用的所有首选项均保存到一个文件中,该文件可以通过调用静态方法 PreferenceManager.getDefaultSharedPreferences(),从应用内的任何位置访问。
1 | SharedPreferences sharedPref = PreferenceManager. |
- 监听首选项变化
要在任一首选项发生更改时收到回调,Activity需要实现 SharedPreference.
OnSharedPreferenceChangeListener 接口,并通过调用 registerOnSharedPreferenceChangeListener() 为 SharedPreferences 对象注册侦听器。
该接口只有 onSharedPreferenceChanged() 一种回调方法,在回调中可以获取变化的Preference和相应的值。
1 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,String key) { |
为了能够保证侦听器不被当做垃圾回收,我们最好在 onResume() 和 onPause() 回调期间分别注册和注销
SharedPreferences.
OnSharedPreferenceChangeListener。
1 | @Override |