天天看点

Android 开发之Preference

在应用开发中经常用到设置。如果想要在你自己的应用中提供设置功能,需要用到Android Preference接口。这样你可以获得和系统设置一样的用户体验。

Android 中包含了一些Preference控件

CheckBoxPreference 复选框控件,将值设置为真或者假

EditTextPreference 弹出一个输入对话框,允许用户输入一串字符串

ListPreference 弹出一个单选列表的对话框,选择一个值

MultiSelectListPreference 复选框列表

RingtonePreference 一个专用的首选项列表,用于选择铃声

虽然可以在代码中动态创建preference,但是大多数还是要在XML文件中去定义preference,因为在xml中有更好的可读性。通常将preference的配置文件保存在res/xml/目录下,虽然文件名可以随便取,但是一般我们会命名为preference.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference
        android:key="pref_sync"
        android:title="@string/pref_sync"
        android:summary="@string/pref_sync_summ"
        android:defaultValue="true" />
    <ListPreference
        android:dependency="pref_sync"
        android:key="pref_syncConnectionType"
        android:title="@string/pref_syncConnectionType"
        android:dialogTitle="@string/pref_syncConnectionType"
        android:entries="@array/pref_syncConnectionTypes_entries"
        android:entryValues="@array/pref_syncConnectionTypes_values"
        android:defaultValue="@string/pref_syncConnectionTypes_default" />
</PreferenceScreen>
           

xml文件的根节点必须是<preference>元素。其他的preference子元素显示为设置列表的一个子条目。preference有几个关键属性

key:当一个preference保存数据的时候,key将作为preference保存数据的唯一ID

title:设置的名称

defaultValue:保存数据的preference的默认的值

当设置的条目过多的时候,我们就可能会用到设置分组了。这样可以使设置的信息更加清晰,明了。使用设置分组有两种方式

1,titles 为不同的分组添加标题

需要使用<:PreferenceCategory>元素,并设置它的title属性,其他preference元素,作为<PreferenceCategory>的子元素

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory 
        android:title="@string/pref_sms_storage_title"
        android:key="pref_key_storage_settings">
        <CheckBoxPreference
            android:key="pref_key_auto_delete"
            android:summary="@string/pref_summary_auto_delete"
            android:title="@string/pref_title_auto_delete"
            android:defaultValue="false"... />
        <Preference 
            android:key="pref_key_sms_delete_limit"
            android:dependency="pref_key_auto_delete"
            android:summary="@string/pref_summary_delete_limit"
            android:title="@string/pref_title_sms_delete"... />
        <Preference 
            android:key="pref_key_mms_delete_limit"
            android:dependency="pref_key_auto_delete"
            android:summary="@string/pref_summary_delete_limit"
            android:title="@string/pref_title_mms_delete" ... />
    </PreferenceCategory>
    ...
</PreferenceScreen>
           

2,subScreens 打开一个新的界面

使用subscreens,把一组preference元素,作为<PreferenceScreen>的子元素即可。

<PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- opens a subscreen of settings -->
    <PreferenceScreen
        android:key="button_voicemail_category_key"
        android:title="@string/voicemail"
        android:persistent="false">
        <ListPreference
            android:key="button_voicemail_provider_key"
            android:title="@string/voicemail_provider" ... />
        <!-- opens another nested subscreen -->
        <PreferenceScreen
            android:key="button_voicemail_setting_key"
            android:title="@string/voicemail_settings"
            android:persistent="false">
            ...
        </PreferenceScreen>
        <RingtonePreference
            android:key="button_voicemail_ringtone_key"
            android:title="@string/voicemail_ringtone_title"
            android:ringtoneType="notification" ... />
        ...
    </PreferenceScreen>
    ...
</PreferenceScreen>
           

有时候我们想要一个preference打开一个不同的界面,而不是设置的界面,比如,点击一个preference想要打开一个浏览器,这时候我们只要在preference元素中添加<Intent>元素即可。

<Preference android:title="@string/prefs_web_page" >
    <intent android:action="android.intent.action.VIEW"
            android:data="http://www.example.com" />
</Preference>
           

PreferenceActivity

要显示设置界面,需要继承PreferenceActivity,一个传统的Activity的封装,可以显示一个设置列表,当其中的设置信息改变是,可以自动保存preference的值。要创建PreferenceActivity还需要在onCreate()方法中,添加自己以定义的preference.xml中的设置信息。添加方法如下:

public class SettingsActivity extends PreferenceActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        <strong>addPreferencesFromResource(R.xml.preferences);</strong>
    }
}
           

Preference Fragment

 当3.0版本以后,官方推荐我们使用PreferenceFragment来代替PreferenceActivity来显示设置信息。因为Fragment为我们的应用提供了更加灵活的设计方式,我们可以把PreferenceFragment添加到任何一个Activity中。使用PreferenceFragment非常简单,只需要继承PreferenceFragment,在onCreate()方法中使用addPreferenceFromResource()来加载preference.xml设置文件。

<pre name="code" class="java">public static class SettingsFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.preferences);
    }
    ...
}
           

创建完成Fragment之后,就可以像其他Fragment一样,添加到Activity中去了

public class SettingsActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Display the fragment as the main content.
        getFragmentManager().beginTransaction()
                .replace(android.R.id.content, new SettingsFragment())
                .commit();
    }
}
           

Preference Headers

当我们说如何为Preference分组时,有两种方法,其中有一种是使用PreferenceScreen打开一个新的页面显示。在3.0版本以后,建议使用headers来代替PreferenceScreen.要在我们的代码中使用headers需要一下四步:

1,将设置选项分组,将不同的组的设置信息放到不同的preference.xml文件中,然后分到不同的PreferenceFragment中显示

2,创建Header文件,每一个Header应该指向一个分组的PreferenceFragment文件

3,扩展PreferenceActivity来显示设置信息

4,实现onBuildHeaders()回调方法来指定headers文件

使用headers最大的好处就是PreferenceActivity能根据屏幕的大小自动调整显示方式,小屏的话,按常规的分两页显示,在大屏上则自动左右布局显示。

创建headers文件,根节点使用<preference-headers>, 其中的每一个节点用<header>表示,选择一个<header>应该打开对应的一个PreferenceFragment

<?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>
           

在<header>中可以添加<extra>元素,可以传递一些键值对到对应的fragment中,在fragment中获取键值对的方法如下

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

显示headers,需要实现onBuildHeaders()回调方法,在其中使用loadHeadersFromResource()方法指定headers文件。

public class SettingsActivity extends PreferenceActivity {
    @Override
    public void onBuildHeaders(List<Header> target) {
        loadHeadersFromResource(R.xml.preference_headers, target);
    }
}
           

继续阅读