Android Preference初探,另一种布局方式

记得android五大数据存储中有个SharePreferences,其他四种分别是:

  1. SQLite数据库
  2. ContentProvider(内容提供者)
  3. 文件存储
  4. 网络存储

这里简单回顾一下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供我们使用。

Android Preference初探,另一种布局方式_第1张图片

其中比较常用的有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。其中:

  • key属性一般都需要,它标识了这个Preference,相当于View的ID,必须唯一,无论是我们要在代码中得到这个Preference的实例还是要保存Preference的数据,都需要一个唯一的key。
  • summary属性就是显示在标题下面的摘要
  • PreferenceCategory用来给Preference设置分组。

(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了。

显示效果:

Android Preference初探,另一种布局方式_第2张图片

对于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>

则效果图:

Android Preference初探,另一种布局方式_第3张图片

点击文本组后:

Android Preference初探,另一种布局方式_第4张图片

可以看到这种分组则是利用PreferenceScreen嵌套包裹Preference的方式来分组的,会将包裹的Preference隐藏,点击该分组后则会显示在一个子屏幕中。

2. Preference点击事件的监听

有了视图,那么用户会操作视图,如点击一下多选框,则需要我们在代码中监听Preference的点击事件。

观察发现,有3个关于Preference事件的方法:

  1. onPreferenceClick()(设置OnPreferenceClickListener)
  2. onPreferenceTreeClick()
  3. onPreferenceChange()(设置OnPreferenceChangeListener)

这三个事件的执行顺序一般也是上面的顺序,其中在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>

其中:

  • fragment属性指定了当我们点击这个header的时候跳转到的fragment
  • extra属性的key和value会被封装到Bundle中,然后使用fragment的getArguments()得到这个Bundle从而得到key对应的value

(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); } }

说明:

  • 不需要重写OnCreate,只需要重写onBuildHeaders加载主屏幕的xml,因为这个Activity只加载Headers。
  • 需要重写isValidFragment并返回true,否则运行会出错。

ok,以下是显示截图:

Android Preference初探,另一种布局方式_第5张图片

Android Preference初探,另一种布局方式_第6张图片

Android Preference初探,另一种布局方式_第7张图片

如果需要兼容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。

你可能感兴趣的:(Android基础,Android进阶)