记得android五大数据存储中有个SharePreferences,其他四种分别是:
这里简单回顾一下SharePreference是的使用:
// 1. 得到sharedPreferences,第一个参数指定SharePreference保存的xml文件的文件名,第二个参数是SharedPreferences模式
SharedPreferences sharedPreferences = getSharedPreferences("demo", Activity.MODE_PRIVATE);
// 2. 保存数据(记得commit)
SharedPreferences.Editor edit = sharedPreferences.edit();
edit.putString("key","value");
edit.commit();
// 3. 获取数据
String value = sharedPreferences.getString("key", "default");
其实,SharePreferences底层是将数据以键值对的方式存储保存在/data/data/package name/shared_prefs下的一个xml文件中。似乎键值对这种数据传递方式很好用,如起源于javascript的json数据格式被广泛应用到各种语言中,致使Android中又多了Json数据解析,而json数据解析似乎又成为了程序员的必修课,而Android Preference也离不开键值对,每个Preference都有一个键值对。
以前我们写布局都是在layout使用View编写布局,而今天我们使用的是Preference构建布局,通常是用在设置模块,这样可以让我们应用设置和系统设置视觉体验一样,风格统一。
1. Android内置Preference的使用
查看android.preference包目录,可以发现Android内置了许多Preference供我们使用。
其中比较常用的有Preference,CheckBoxPreference,EditTextPreference,ListPreference。下面我们动手简单的使用一下这些Preference。
步骤:
(1)在res/xml文件夹下建立xml文件,如:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/textView">
<Preference android:key="preference"
android:title="@string/show_text"
android:defaultValue="文本值"
android:summary="@string/text_summary" />
PreferenceCategory>
<PreferenceCategory android:title="@string/edit_text">
<EditTextPreference android:key="edittext_preference"
android:title="@string/edit_text"
android:summary="@string/edit_summary"
android:dialogTitle="@string/edit_dialog_title">
EditTextPreference>
PreferenceCategory>
<PreferenceCategory android:title="@string/checkbox">
<CheckBoxPreference android:key="checkbox_preference1"
android:title="@string/selection_1"
android:summary="@string/selection_summary_1">
CheckBoxPreference>
PreferenceCategory>
<PreferenceCategory android:title="@string/single_selection">
<ListPreference android:key="list_preference"
android:title="@string/single_selection"
android:summary="@string/single_select_summary"
android:entries="@array/single_selection"
android:entryValues="@array/single_selection_value">
ListPreference>
PreferenceCategory>
<PreferenceCategory android:title="@string/toggle">
<SwitchPreference
android:key="switch_preference"
android:title="@string/toggle"
android:textOn="@string/on"
android:textOff="@string/off">
SwitchPreference>
PreferenceCategory>
PreferenceScreen>
上面用到的内置Preference都会被系统自动显示在屏幕上,形成一种View。其中:
(2)新建一个Activity继承PreferenceActivity,如:
public class SettingsActivity extends PreferenceActivity {
private static final String TAG = "SettingsActivity";
private SharedPreferences mDefaultSharedPreferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.activity_settings);
}
}
在onCreate方法中调用addPreferencesFromResource()方法添加我们自定义的xml布局就ok了。
显示效果:
对于Preference的使用比较简单。除了上面的那种Preference分组外,我们还可以子屏幕的方式来给Preference进行分组,如将上面的xml修改为:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen
android:key="text"
android:title="@string/text">
<Preference
android:title="@string/show_text"
android:defaultValue="文本值"
android:summary="@string/text_summary" />
<EditTextPreference android:key="edittext_preference"
android:title="@string/edit_text"
android:summary="@string/edit_summary"
android:dialogTitle="@string/edit_dialog_title">
EditTextPreference>
PreferenceScreen>
<PreferenceCategory android:title="@string/checkbox">
<CheckBoxPreference android:key="checkbox_preference1"
android:title="@string/selection_1"
android:summary="@string/selection_summary_1">
CheckBoxPreference>
PreferenceCategory>
<PreferenceCategory android:title="@string/single_selection">
<ListPreference android:key="list_preference"
android:title="@string/single_selection"
android:summary="@string/single_select_summary"
android:entries="@array/single_selection"
android:entryValues="@array/single_selection_value">
ListPreference>
PreferenceCategory>
<PreferenceCategory android:title="@string/toggle">
<SwitchPreference
android:key="switch_preference"
android:title="@string/toggle"
android:summary="@string/switch_summary"
android:textOn="@string/on"
android:textOff="@string/off">
SwitchPreference>
PreferenceCategory>
PreferenceScreen>
则效果图:
点击文本组后:
可以看到这种分组则是利用PreferenceScreen嵌套包裹Preference的方式来分组的,会将包裹的Preference隐藏,点击该分组后则会显示在一个子屏幕中。
2. Preference点击事件的监听
有了视图,那么用户会操作视图,如点击一下多选框,则需要我们在代码中监听Preference的点击事件。
观察发现,有3个关于Preference事件的方法:
这三个事件的执行顺序一般也是上面的顺序,其中在onPreferenceClick返回值中返回true时则不会执行第三个方法。
监听到点击事件后,我们可以执行我们自己的操作,如打开一个新的Activity,弹出对话框或打开一个网页等等,不过可以用Intent的操作,还有更简单的方法。
只需在相应的Preference下添加一个intent,即可执行intent:
<Preference
android:key="preference"
android:title="@string/show_text"
android:defaultValue="文本值"
android:summary="@string/text_summary">
<intent android:action="android.intent.action.VIEW"
android:data="http://www.baidu.com" />
Preference>
3. Preference设置默认值
通过Preference的defaultValue属性设置默认值,这个值系统会在用户第一次打开该应用的时候保存到SharePreferences中作为该Preference的默认值。
4. Preference数据的保存
每个Preference都有一个键值对,系统根据这个键值对自动将Preference的值保存到SharePreferences中,当我们需要根据Preference的值确定用户的行为时,如开关打开和开关关闭状态,我们代码的执行逻辑。这个时候,我们只需要读取SharePreference即可得到这个值。
getPreferenceManager().getDefaultSharedPreferences(this)
通过上面的代码,我们可以得到系统保存Preference值的那个SharedPreferences,然后我们可以与SharedPreferences交互。
5. Preference Headers的使用
Preference Headers是Android 3.0之后引入的可以使得第一个屏幕只显示分组列表,而不是显示分组的子屏幕列表,这也是除了用PreferenceScreen嵌套构建子屏幕的另一种方法。
在Android 3.0及更高的版本中,我们可以使用Headers功能构建子屏幕
步骤:
(1)编写preference headers的xml
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
<header
android:title="@string/prefs_category_one"
android:fragment="com.example.lt.preference.SwitchFragment"
android:summary="@string/prefs_summ_category_one">
<extra android:name="type" android:value="数据连接" />
header>
<header
android:title="@string/prefs_category_two"
android:fragment="com.example.lt.preference.SwitchFragment"
android:summary="@string/prefs_summ_category_two" >
<extra android:name="type" android:value="多选框" />
header>
preference-headers>
其中:
(2)编写子屏幕的xml布局和代码
数据连接的xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<SwitchPreference
android:key="switch_preference1"
android:title="@string/data_connection"
android:summary="@string/data_connection_summary"
android:textOn="@string/on"
android:textOff="@string/off">
SwitchPreference>
<SwitchPreference
android:key="switch_preference2"
android:title="@string/wifi_connection"
android:summary="@string/wifi_connection_summary"
android:textOn="@string/on"
android:textOff="@string/off">
SwitchPreference>
PreferenceScreen>
多选框的xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="checkbox1"
android:title="@string/selection_1"
android:summary="@string/selection_summary_1">
CheckBoxPreference>
<CheckBoxPreference
android:key="checkbox2"
android:title="@string/selection_2"
android:summary="@string/selection_summary_2">
CheckBoxPreference>
PreferenceScreen>
这里编写的两个xml布局对应了上面的两个header,所以还需要编写Fragment
public class SwitchFragment extends PreferenceFragment{
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String type = getArguments().getString("type");
if(type.equals("数据连接")){
addPreferencesFromResource(R.xml.switch_header);
}else{
addPreferencesFromResource(R.xml.checkbox_header);
}
}
}
可以看到这里根据xml中header的extra属性指定的value加载不同的布局,是因为我们两个header共用了这个Fragment。
(3)编写主屏幕代码
主屏幕需要用一个PreferenceActivity显示:
public class SettingsActivity extends PreferenceActivity{
@Override
protected boolean isValidFragment(String fragmentName) {
return true;
}
@Override
public void onBuildHeaders(List target) {
loadHeadersFromResource(R.xml.preference_headers,target);
}
}
说明:
ok,以下是显示截图:
如果需要兼容Android 3.0及更低版本,则需要利用intent标签,我们可以在主屏幕中添加两个Preference,并设置intent标签,由于Andoroid 3.0以下没有Fragment,也就没有PreferenceFragment,所以主屏幕需要一个Activity,子屏幕也需要一个Activity(公用),通过intent的Action的值在子屏幕activity的onCreate方法中使用addPreferencesFromResource()方法加载不同的xml布局,记得判断一下Android版本。
总结:Android Preference作为Android中新的一种布局方式,通常用在Settings模块中,使得我们自己应用的设置风格也能像系统设置一样,达成一种视觉上的统一,其使用比较简单,有点类似于View。