1、什么是Preference
Preference 直译为偏好,类似用户设置喜好选项的东西,就像工厂的机器按钮设置,设置好就保持这个状态,以达到用户的选择的目的。这是以列视图显示的一种UI构件,地位相似于Listview,这个构件出现在Activity中,跟SharedPreference的存取有关,而其xml的布局文件的结构也是层级化的,和一般的layout布局类似。这个类有个Key值,这个值和SharedPreference的存储有关,能自动保存这些数据。
2、怎么编写preference
第一步:先创建preference的布局,在资源文件要先建立一个xml的文件夹,在res/xml/下编写preference XML的布局:
<?xml version="1.0" encoding="utf-8"?>
<!-- preference的组织方式有PreferenceScreen和PreferenceCategory,PreferenceCategory是带层次组织关系,在后面的例子体验,而PreferenceScreen就是最平白和基础的方式 -->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 有四个基本组建,这个例子学习两个。里面的内容对照图,很容易理解,RingtonePreference是选择铃音,这里给出两个选择,系统默认的铃音和无声 -->
<CheckBoxPreference android:key="checkbox"
android:title="CheckBox Preference"
android:summary="Check it on , check it off"/>
<RingtonePreference android:key="ringtone"
android:title="Ringtone Preference"
android:showDefault="true"
android:showSilent="true"
android:summary="Pick a tone, any tone"/>
</PreferenceScreen>
看到常用的组建有六个:CheckBoxPreference、RingtonePreference、ListPreference、EditTextPreference、MutiSelectPreference、SwitchPreference。
CheckBoxPreference 就是单选框啦,其中有些属性有必要提一下,Android:summaryOn和android:summaryOff,这个表示在选择和不选的时候显示的描述文字,这个组件在SharedPreference上存储的值是boolean,从拉取出来的xml文件可以看到:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<boolean name="its_first_value" value="true" />
<boolean name="its_second_value" value="false" />
……
</map>
而且要说的是,在同一个项目的res/xml创建不同preference文件,可以在不同的文件中设置同一个key的值,虽然使用的地方不同,但是实际都指向同一个preference值,只是在不同的preference UI中表现。
RingtonePreference 的更好理解,就是选择系统的铃声,正常使用的时候,这个组件一般用不到,比如给应用选择背景音乐之类,选择音乐之后,preference的存储文件的内容如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
... ...
<string name="ringtone_pre">content://settings/system/xxxxxxx</string>
... ...
</map>
然后是 ListPreference,这个组件的使用很频繁,它使得用户可以在一堆选项中进行选择。具体表现为弹出一个Radio Button列表形式的对话框,用户点击某个选项后,保存点击数据并消灭对话框,而后就算消灭Activity后打开,上次点击的选项依旧保存。
在xml文件中定义布局的时候,如下:
<ListPreference android:key="selected_size_settings" 可以通过key来获取preference
android:title="Size settings"
android:summary="select your ass"
android:entries="@array/details" list的内容
android:entryValues="@array/details_values" list各内容对应的value
android:dialogTitle="Choose your selections" 弹出框的标题
android:defaultValue="1"/> <!-- 对应为entryValues的值,缺省1,即缺省为Number of Stops。 -->
其中的两个数据,定义在res/values/array.xml的文件中:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="details">
<item>small</item>
<item>common</item>
<item>big</item>
</string-array>
<string-array name="details_values">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
</resources>
要得到sp保存的数据,通过DDMS的文件导出:/data/data//shared_prefs/_preferences.xml。但是注意key值有也只能有一个。
在代码中,我们也可以动态的获取用户设置的preferences值,本应用的其他activity也可读取:
//通过preferences管理器获取本应用的preferences。参数this将使用本package的名字来寻找保存文件。
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String option = prefs.getString("selected_flight_sort_option", "1");
当然preferences也可以被其他应用获取,preference activity 也可以被 intent 唤起,比如设置类型:
<activity android:name=".MyPreferenceActivity" android:label="@string/list_preferences" >
<intent-filter>
<action android:name="com.me.example.intent.action.MyPreferences" />
<category android:name="android.intent.category.PREFERENCE"/>
</intent-filter>
</activity>
EditText Preference也是比较常用的,重要的属性有android:defaultValue=”xxx”,用于设置默认值。得到存储的值是String类型的,这个内容不多。
然后是 MultiSelect List Preference ,它的实现类似于 ListPreference,不同的是用户可以不选或者多选。在数据保存是用的 Set 形式,读取也要用 set 的数组的方式。
现在看看 PreferenceCategory ,在preference的总布局中,这个是在 Preference 列表中显示分组,在xml文件是以 Preference Screen 嵌套多个并列的 Preference Category 。如下:
<PreferenceScreen xmlns:Android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:key="meats_category"
android:title="Meats"
android:summary="Preferences related to meats">
<CheckBoxPreference android:key="fish_selection_pref"
android:title="Fish"
android:summary="Fish is Healthy"/>
<CheckBoxPreference … />
<CheckBoxPreference … />
</PreferenceCategory>
<PreferenceCategory android:key="vegitable_category"
android:title="Vegetables"
android:summary="Preference related to Vegetables">
<CheckBoxPreference android:key="tomato_selection_pref"
android:title="Tomato"
android:summary="It's actually a fruit."/>
<CheckBoxPreference …/>
</PreferenceCategory>
</PreferenceScreen>
还有一个重要的东西,当我们选择 A 组件时,B 组件才可以被操作,若不选 A 的话,B就是显示不可用的那种灰色。这个功能就是在组件的xml中加一个属性:
<CheckBoxPreference android:key="AAAA"
android:title="AAAA"/>
<EditTextPreference android:key="B"
android:layout="?android:attr/preferenceLayoutChild"
android:title="BBBB"
android:dependency="AAAA"/> <!-- 设置关联,只有key为AAAA的为true,才enable本perf,同时通过android:attr/设置layout的格式 -->
我们也可以利用 preference 保存数据,写入 preference 数据,使用 editor 类对 preference 对象的数据进行编辑:
private final String HIGH = "initialized";
private final String CALLNUM = "call_number";
private void dataStore(){
//等同于PreferenceManager.getDefaultSharedPreferences(this);或者通过getShearedPreferences(name,mode)来指定文件名,可以通过editor来写。除了MODE_PRIVATE外,还有MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,这是用来创建preference是设置的权限。如果我们只限于本应用使用,可设置MODE_PRIVATE。
SharedPreferences prefs = getPreferences(MODE_PRIVATE);
boolean hasPreferences = prefs.getBoolean(HIGH, false);
int num = prefs.getInt(CALLNUM, 0);
if(hasPreferences){
Log.d("PRO","We've been called " + num + " times before. ");
}else{
Log.d("PRO","First time ever being called.");
}
//写入preference
Editor editor = prefs.edit();
editor.putBoolean(HIGH, true);
num ++;
editor.putInt(CALLNUM, num);
editor.commit(); //或者editor.apply();
}
最后是 DialogPreference ,DialogPreference 是 EditTextPreference 和 ListPreference 的基类,如果我们需要有自己的弹框效果,可以继承 DialogPreference 来自定制 layout,点击触发处理,并在 onDialogClose() 中处理写 preference 文件。