Android(安卓)API Guides---Settings
Settings
应用程序通常包括设置,允许用户修改应用程序的功能和行为。例如,一些应用程序允许用户指定通知是否启用或指定应用程序的频率同步数据与云。
如果您想为您的应用程序的设置,你应该使用Android的偏好API来构建与其他Android应用(包括系统设置),用户的体验是一致的接口。本文介绍了如何建立使用偏好的API应用设置。
设置设计
有关如何设计你设置的信息,请阅读设置设计指南。
图1.从Android短信应用的设置截图。选择由偏好定义的项目打开来更改设置的接口。
概观
而不是使用视图对象构建用户界面,设置使用您在XML文件中声明优先级的不同子类中建。
A优先股对象是单个设置积木。每个偏好显示为列表中的一个项目,并为用户提供了修改设置适当的UI。例如,一个CheckBoxPreference创建一个列表项,显示一个复选框,一个ListPreference创建打开与一个选择列表的对话框的一个项目。
每次添加偏好具有系统用来保存设置为您的应用程序的设置默认SharedPreferences文件中的相应键值对。当用户更改设置,系统更新为你SharedPreferences文件的相应值。你应该直接与相关的SharedPreferences文件交互的唯一时间是当你需要以确定根据用户设置你的应用程序的行为来读取值。
保存在SharedPreferences每个设置可以是以下数据类型之一的值:
- Boolean
- Float
- Int
- Long
- String
- String
Set
因为你的应用程序的设置界面使用偏好对象视图对象,而不是建造,需要使用专门的活动或片段的子类来显示列表的设置:
如果您的应用程序支持Android版本低于3.0(API级别10,下)长大,你必须构建活动为PreferenceActivity类的一个扩展。
在Android 3.0及更高版本,您应该改用承载显示您的应用程序设置的PreferenceFragment的传统活动。但是,您也可以使用PreferenceActivity创建,当你有设置多组大屏幕的双面板布局。
如何建立你的PreferenceActivity和PreferenceFragment的实例有关创建活动偏好和使用偏好的碎片的部分进行了讨论。
优先
为您的应用程序的每个设置由优先类的特定子类来表示。每个子类包括一组核心属性允许您指定的东西,如用于设定的标题和默认值。每个子类还提供了它自己的专用的属性和用户界面。例如,图1显示了从消息应用程序的设置截图。在设置画面中每个列表项由不同的偏好对象的支持。
一些最常见的偏好是:
CheckBoxPreference
显示与该被启用或禁用设置一个复选框的项目。保存的值是一个布尔值(如果是真的它的选中)。
ListPreference
打开带有单选按钮列表的对话框。所保存的值可以是所支持的值的类型(如上所列)中的任一项。
EditTextPreference
打开带有一个EditText小部件的对话框。保存的值是一个字符串。
见偏好类的所有其他亚类和其对应的属性的列表。
当然,内置的类并不适合每一个需要和你的应用程序可能需要一些更加专业化。例如,平台目前没有用于拾取一个数字或日期提供偏好类。所以,你可能需要定义自己偏好的子类。这样做的帮助,请参阅有关构建自定义偏好部分。
在XML定义预置
虽然你可以在运行时新实例化对象的偏好,你应该优先对象的层次结构定义XML您的设置列表。使用XML文件来定义优先您的收藏的设置,因为该文件提供了一个易于阅读的结构是简单的更新。此外,您的应用程序的设置一般是预先确定的,但你仍然可以修改集合在运行时。
每个子类偏好可以与相匹配的类名的XML元素,比如<CheckBoxPreference>声明。
您必须保存XML文件在res / XML /目录下。虽然你可以命名你想要的任何文件,它是传统的preferences.xml命名。你通常只需要一个文件,因为在层次结构的分支(即打开自己的设置列表)使用PreferenceScreen嵌套实例宣告。
注:如果您想为您的设置多窗格布局,那么你需要单独的XML文件中的每个片段。
为XML文件根节点必须是<PreferenceScreen>元素。在这个元素就是你添加的每个偏好。每次添加<PreferenceScreen>元素中孩子出现在设置列表中的单个项目。
例如:
<?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>在这个例子中,有一个CheckBoxPreference和ListPreference。两个项目包括以下三个属性:
android:key
此属性是必需的持久化的数据值的偏好。它指定唯一的密钥(字符串)保存在SharedPreferences此设定值时,系统使用。
在不需要此属性的唯一实例是当偏好是一个PreferenceCategory或PreferenceScreen,或偏好指定一个Intent调用(与<意图>元素)或显示一个片段(使用Android:片段属性)。
android:title
这为设置一个用户可视名称。
android:defaultValue
这指定系统应在SharedPreferences文件中设置的初始值。你应该为所有设置提供一个默认值。
有关其他所有支持的属性信息,请参见偏好(以及相应的子类)的文档。
图2.标题设置的类别。
1.类别由<PreferenceCategory>元素中指定。
title属性:2,标题与Android指定。
当您的设置列表超过约10个项目,你可能要添加标题定义的设置组或单独的屏幕上显示这些组。这些选项在下面的章节中描述。
创建设置组
如果你目前的10个或更多的设置列表中,用户可能难以扫描,理解和处理它们。可以通过将一些或全部的设置成组,有效地将一个长列表分为多个较短的列表解决这个问题。一组相关的设置,可以通过以下两种方式之一提交:
- Using titles
- Using subscreens
使用标题
如果你想为用户提供的设置组标题之间分隔(如图2),将每个组内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>使用 subscreens
如果您想放置的设置组到子屏幕(如图3所示),将组内PreferenceScreen偏好的对象。
图3.设置防晒霜。在<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>使用意图
在某些情况下,你可能需要一个首选项,打开不同的活动,而不是设置屏幕,如Web浏览器查看网页。要调用当用户选择首选项目的意向,添加一个<意图>元素对应的<优先>元素的子元素。
例如,这里是你如何使用首选项目打开一个网页
<Preference android:title="@string/prefs_web_page" > <intent android:action="android.intent.action.VIEW" android:data="http://www.example.com" /></Preference>您可以通过以下属性创建的隐式和显式意图:
android:action
的动作来分配,按所述的setAction()方法。
android:data
数据分配,因为每setData()方法。
android:mimeType
MIME类型分配,因为按照的setType()方法。
android:targetClass
组件的名称,该类一部分,每setComponent()方法。
android:targetPackage
组件名称的包装部分,因为每setComponent()方法。
创建活动优先
要在活动显示您的设置,扩展PreferenceActivity类。这是一个显示基于偏好对象的层次设置的列表传统活动类的扩展。该PreferenceActivity自动持续与当用户进行了更改每个偏好相关的设置。
注意:如果您正在开发针对Android 3.0及更高的应用程序,则应该使用PreferenceFragment。转到大约使用偏好碎片下一节。
要记住的最重要的事情是,你不是的onCreate()回调过程中加载的意见布局。相反,你叫addPreferencesFromResource()添加在一个XML文件到活动中你声明的偏好。例如,下面是一个功能PreferenceActivity最低要求的代码:
public class SettingsActivity extends PreferenceActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); }}这实际上是对某些应用足够的代码,因为只要用户修改的偏好,系统将更改保存到默认SharedPreferences文件,当你需要检查用户的设置的其他应用程序组件可以读取。许多应用程序,但是,需要以多一点的代码来监听所发生的偏好的变化。有关听着SharedPreferences文件更改的信息,请参阅有关阅读喜好的部分。
使用偏好碎片
如果你正在为Android 3.0(API级11)和更高的发展,你应该使用PreferenceFragment来显示自己的喜好对象列表。您可以将PreferenceFragment添加到任何活动,你不需要使用PreferenceActivity。
片段为应用程序提供一个更灵活的架构,相比于单独的活动,无论你正在构建什么样的活动。因此,我们建议您使用PreferenceFragment可能的情况下控制你设置的显示,而不是PreferenceActivity的。
你的实现PreferenceFragment都可以作为定义onCreate()方法来加载与addPreferencesFromResource一个首选项文件()一样简单。例如:
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); } ...}然后,您可以将此片段添加到活动就像你其他任何片段。 例如:
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(); }}注:PreferenceFragment没有一个自己的上下文对象。如果你需要一个Context对象,你可以调用getActivity()。但是,要小心调用getActivity()只有当片段连接到一个活动。当该片段尚未连接,或者其生命周期,getActivity年底期间分离()将返回null。
设置默认值
你可能创建的喜好定义一些重要的行为为您的应用程序,让你初始化相关SharedPreferences使用默认值文件为每个偏好,当用户第一次打开你的应用程序是必要的。
你必须做的第一件事就是指定使用了Android在XML文件中的每个对象优先默认值:DefaultValue特性。的值可以是任何数据类型适合于对应的偏好对象。 例如:
<!-- default value is a boolean --><CheckBoxPreference android:defaultValue="true" ... /><!-- default value is a string --><ListPreference android:defaultValue="@string/pref_syncConnectionTypes_default" ... />然后,从您的应用程序的主的onCreate()方法的活动,并通过它用户可以输入首次呼叫setDefaultValues)您的应用程序(任何其他活动:
PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);的onCreate()中调用这可以确保您的应用程序正常初始化使用默认设置,您的应用程序可能需要以确定某些行为(如是否下载,而蜂窝网络上的数据)来读取。
这个方法有三个参数:
您的应用程序上下文。
对于您想设置的默认值偏好XML文件的资源ID。
一个布尔指示默认值是否应该设置多于一次。
当假的,系统将只有这种方法从未叫过去的默认值(默认值共享偏好设置文件或KEY_HAS_SET默认值为false)。
只要你设置第三个参数为false,你可以安全地调用每一个你的活动启动的同时,并未重置为默认值覆盖用户的喜好保存时间此方法。但是,如果你把它设置为true,将覆盖在默认以往任何值。
使用偏好头
在极少数情况下,你可能会想设计自己的设置,使得第一屏幕显示只有subscreens的列表(如在系统设置中的应用程序,如图4所示和图5)。当你开发Android 3.0及更高版本,你应该在Android 3.0的使用新的“头文件”功能,这样的设计,而不是与嵌套PreferenceScreen元素的建筑subscreens。
建立与头设置,您需要:
分隔每个组设置成PreferenceFragment的单独实例。即,每个组的设置需要一个单独的XML文件。
创建一个XML文件标题列出每个设置组,并宣布该片段包含的设置相应的列表。
扩展PreferenceActivity类来承载您的设置。
实施onBuildHeaders()回调到指定的头文件。
一个伟大的好处是用这种设计是PreferenceActivity自动显示在大屏幕上运行时,图4所示的两个窗格布局。
即使您的应用程序支持Android年龄大于3.0的版本,你可以建立自己的应用程序在新设备使用PreferenceFragment一两窗格演示,同时还旧设备上支持传统的多画面层次(请参见关于支持老版本使用偏好头)
图4.头两窗格布局。
1.头与一个XML头文件中定义。
2.设置每个组是由是由在头文件中的<header>元素指定的PreferenceFragment定义。
图5.设置标题的手持设备。当选择了一个项目,相关PreferenceFragment更换头。
创建头文件
在你的头列表设置每个组由一个根<偏好头>元素中一个<header>元素指定。 例如:
<?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>随着Android:片段属性,每一个标题声明PreferenceFragment的一个实例,当用户选择的标题应该打开。
在<附加功能>元素可以让你键值对传递到以捆绑片段。该片段可以通过调用getArguments检索参数()。你也许参数传递给片段为各种各样的原因,但有很好的理由是重用PreferenceFragment的同一小类每个组并使用参数来指定哪些偏好XML文件片段应加载。
例如,下面是一个可以多设置组重用的片段,当每头定义了一个<额外>参数的“设置”键:
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); } }}显示标题
要显示偏好头,您必须实现onBuildHeaders()回调方法并调用loadHeadersFromResource()。 例如:
public class SettingsActivity extends PreferenceActivity { @Override public void onBuildHeaders(List<Header> target) { loadHeadersFromResource(R.xml.preference_headers, target); }}当用户选择从标题的列表中的项目,系统将打开相关PreferenceFragment。
注意:当使用偏好头,你PreferenceActivity的子类并不需要实现onCreate()方法,因为该活动的唯一需要的任务就是装载头。
支持老版本具有优先头
如果您的应用程序支持Android年龄大于3.0版本中,你仍然可以使用头文件在Android3.0及更高版本上运行时提供了双面板布局。所有你需要做的就是创建一个使用行为类似标题的项目基本<首选项>元素的额外优惠XML文件(由较旧的Android版本一起使用)。
而不是打开一个新PreferenceScreen的,然而,每一个<偏好>的元素发送意向指定要加载的偏好XML文件PreferenceActivity。
例如,下面的是在Android3.0及更高版本(RES / XML /喜好headers.xml)用于优先头的XML文件:
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> <header android:fragment="com.example.prefs.SettingsFragmentOne" android:title="@string/prefs_category_one" android:summary="@string/prefs_summ_category_one" /> <header android:fragment="com.example.prefs.SettingsFragmentTwo" android:title="@string/prefs_category_two" android:summary="@string/prefs_summ_category_two" /></preference-headers>这里是它提供了比Android3.0(RES / XML / preference_headers_legacy.xml)老版本相同的头一个首选项文件:
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <Preference android:title="@string/prefs_category_one" android:summary="@string/prefs_summ_category_one" > <intent android:targetPackage="com.example.prefs" android:targetClass="com.example.prefs.SettingsActivity" android:action="com.example.prefs.PREFS_ONE" /> </Preference> <Preference android:title="@string/prefs_category_two" android:summary="@string/prefs_summ_category_two" > <intent android:targetPackage="com.example.prefs" android:targetClass="com.example.prefs.SettingsActivity" android:action="com.example.prefs.PREFS_TWO" /> </Preference></PreferenceScreen>因为对于<偏好头>支持Android 3.0的加入,系统上Androd3.0或更高版本上运行,只有当调用onBuildHeaders()在你的PreferenceActivity。为了加载了“遗产”头文件(偏好头legacy.xml),必须检查Android版本,如果版本低于3.0的Android(蜂窝)年纪大了,叫addPreferencesFromResource()来加载传统的头文件。 例如:
@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { // Load the legacy preferences headers addPreferencesFromResource(R.xml.preference_headers_legacy); }}// Called only on Honeycomb and later@Overridepublic void onBuildHeaders(List<Header> target) { loadHeadersFromResource(R.xml.preference_headers, target);}剩下要做的唯一事情就是搞定的传入活动,以确定要加载的首选项文件的意图。所以检索的意图行动,并把它比作是您在偏好XML <目的>标签中使用已知的动作字符串:
final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE";...@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String action = getIntent().getAction(); if (action != null && action.equals(ACTION_PREFS_ONE)) { addPreferencesFromResource(R.xml.preferences); } ... else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { // Load the legacy preferences headers addPreferencesFromResource(R.xml.preference_headers_legacy); }}谨防)的连续调用addPreferencesFromResource(会叠加在一个列表中的所有喜好,所以要确保它只能通过链接的条件调用一次,否则-if语句。
阅读喜好
默认情况下,所有的应用程序的偏好被保存到一个文件,该文件通过调用静态方法PreferenceManager.getDefaultSharedPreferences是从你的应用程序中任何地方访问()。这将返回SharedPreferences对象包含所有与你PreferenceActivity使用的优先对象关联的键 - 值对。
例如,这里是你如何能读取应用程序中的任何其他活动的优先值之一
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "");监听偏好的变化
还有你可能想尽快用户改变首选项之一通知有几个原因。为了通过调用registerOnSharedPreferenceChangeListener接收回调时的变化发生的偏好中的任何一个,实行SharedPreferences.OnSharedPreferenceChangeListener接口并注册了SharedPreferences对象听者()。
该接口只有一个回调方法,onSharedPreferenceChanged(),你可能会发现它最容易实现的接口为您的活动的一部分。 例如:
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener { public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType"; ... public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(KEY_PREF_SYNC_CONN)) { Preference connectionPref = findPreference(key); // Set summary to be the user-description for the selected value connectionPref.setSummary(sharedPreferences.getString(key, "")); } }}在这个例子中,该方法检查所改变的设置是否为已知的偏爱项。它调用findPreference()来获取已更改,以便它可以修改的项目的总结是用户选择的描述偏好的对象。也就是说,当设置为一个ListPreference或其他选择题的设置,你应该叫setSummary()时设置更改为显示(例如图5所示的睡眠设置)的当前状态。
注意:有关设置Android的设计文档中描述,我们建议您每一个用户为了描述当前设置更改的偏好更新时间为ListPreference摘要。
对于在活动中适当的生命周期管理,我们建议您注册和onResume()和期间的onPause你注销SharedPreferences.OnSharedPreferenceChangeListener()回调,分别为:
@Overrideprotected void onResume() { super.onResume(); getPreferenceScreen().getSharedPreferences() .registerOnSharedPreferenceChangeListener(this);}@Overrideprotected void onPause() { super.onPause(); getPreferenceScreen().getSharedPreferences() .unregisterOnSharedPreferenceChangeListener(this);}注意:当你调用registerOnSharedPreferenceChangeListener(),偏好管理器不会保存当前强烈的参考监听器。您必须存储的强引用监听器,否则会容易受到垃圾收集。我们建议您保持,只要您需要的侦听器将存在一个对象的实例数据到听者的参考。
例如,在下面的代码,调用方不保留对侦听器的引用。其结果是,听者会受到垃圾收集,它会在未来的某个不确定的时间失败:
prefs.registerOnSharedPreferenceChangeListener( // Bad! The listener is subject to garbage collection! new SharedPreferences.OnSharedPreferenceChangeListener() { public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { // listener implementation }});相反,存储在只要需要监听,将存在一个对象的一个实例的数据字段中的监听器的参考:
SharedPreferences.OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() { public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { // listener implementation }};prefs.registerOnSharedPreferenceChangeListener(listener);管理网络使用
与Android 4.0开始,系统的设置应用程序允许用户看到他们的应用程序的网络有多少数据在前台和后台使用一段时间。然后,用户可以禁止使用单个应用程序的背景资料。为了避免用户禁用您的应用从后台数据的访问,那么应该有效地利用数据连接,并允许用户通过应用程序的设置优化您的应用程序的数据使用量。
例如,可以允许用户控制您的应用程序的频率同步的数据,你的应用程序是否执行上传/只时,通过Wi-Fi下载,您的应用程序是否使用数据漫游时,等有了提供给他们这些控件,用户不太可能,当他们接近,他们在系统设置中设置的限制禁用您的应用程序的访问数据,因为它们可以代替精确地控制您的应用程序有多少数据使用。
一旦你在你的PreferenceActivity控制应用数据的习惯添加了必要的喜好,你应该在你的清单文件中添加了一个ACTION_MANAGE_NETWORK_USAGE意图过滤器。例如
<activity android:name="SettingsActivity" ... > <intent-filter> <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter></activity>这个意图过滤指示系统,这是一种控制应用程序的数据使用量的活动。因此,当用户检查多少数据您的应用程序从系统的设置应用程序使用,查看一个应用程序设置按钮是可用的启动您的PreferenceActivity,使用户可以优化您的应用程序有多少数据使用。
构建自定义偏好
Android框架包括各种偏好的子类,允许你建立一个UI几种不同类型的设置。不过,你可能会发现你需要一种没有内置的解决方案,如数字选择器或日期选择器的设置。在这种情况下,你需要通过扩展偏好类或其它子类来创建自定义的偏好。
当你扩展的优先级,有你需要做一些重要的事情:
指定当用户选择的设置显示的用户界面。
在适当的时候保存设置值。
初始化当前(或默认)值的偏好时,映入眼帘。
当由系统要求提供的默认值。
如果偏好,提供自己的用户界面(例如一个对话框),保存和恢复状态,以处理生命周期的变化(当用户旋转屏幕等)。
以下各节介绍如何完成这些任务。
指定用户界面
如果直接延长偏好类,你需要实现的onClick()来定义,当用户选择项目时发生的操作。然而,大多数的自定义设置延伸DialogPreference显示一个对话框,从而简化了程序。当你扩展DialogPreference,你必须调用setDialogLayoutResourcs()在类的构造函数中指定对话框的布局。
例如,下面是声明的布局,并指定为默认的正面和负面的对话框按钮上的文本自定义DialogPreference构造函数:
public class NumberPickerPreference extends DialogPreference { public NumberPickerPreference(Context context, AttributeSet attrs) { super(context, attrs); setDialogLayoutResource(R.layout.numberpicker_dialog); setPositiveButtonText(android.R.string.ok); setNegativeButtonText(android.R.string.cancel); setDialogIcon(null); } ...}保存设置的值
你可以通过调用的偏好类的persist*()方法,如持续性()如果设定值是一个整数或持续布尔()来保存一个布尔之一,保存在任何时候设定一个值。
注:每个偏好只能保存一个数据类型,所以必须使用持续*()方法适合你的自定义偏好使用的数据类型。
当你选择坚持的设置可以依靠其优先类,你扩展。如果扩展DialogPreference,那么你应该在对话框关闭时,只有坚持价值因阳性结果(用户选择“确定”按钮)。
当一个DialogPreference关闭时,系统将调用onDialogClosed()方法。该方法包括,指定用户结果是否为“积极” - 如果该值为true一个布尔参数,那么用户选择的正面按钮,你应该保存新值。 例如:
@Overrideprotected void onDialogClosed(boolean positiveResult) { // When the user selects "OK", persist the new value if (positiveResult) { persistInt(mNewValue); }}在这个例子中,mNewValue是一个类的成员持有的设定的当前值。调用persistInt()保存价值的SharedPreferences文件(自动使用的XML文件中指定此偏好的关键)。
初始化电流值
当系统增加您的喜好在屏幕上,它调用onSetInitialValue()来通知您设置是否具有持久的价值。如果没有持久的价值,这个调用为您提供的默认值。
该onSetInitialValue()方法传递一个布尔值,restorePersistedValue,表明是否值已经持续了设置。如果这是真的,那么你应该通过调用优先级的getPersisted *()方法,如getPersistedInt()为整数值1检索坚持价值。通常你会想检索持久的价值,以便您可以正确地更新UI以反映先前保存的价值。
如果restorePersistedValue是假的,那么你应该使用在第二个参数传递的默认值。
@Overrideprotected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { if (restorePersistedValue) { // Restore existing state mCurrentValue = this.getPersistedInt(DEFAULT_VALUE); } else { // Set default state from the XML attribute mCurrentValue = (Integer) defaultValue; persistInt(mCurrentValue); }}每个getPersisted*()方法采用指定情况下使用默认值实际上是没有持久的价值或该键不存在的说法。在上面的例子中,一个本地常数用于指定在壳体getPersistedInt()的默认值不能返回一个持久的值。
注意:不能使用将默认值作为getPersisted*()方法的默认值,因为它的值是当restorePersistedValue是真的总是空。
提供缺省值
如果您喜欢的类的实例指定一个默认值(用android:DefaultValue特性),那么系统调用onGetDefaultValue()时,它实例化对象,以检索值。你必须按顺序执行,以便系统保存在SharedPreferences默认值此方法。 例如:
@Overrideprotected Object onGetDefaultValue(TypedArray a, int index) { return a.getInteger(index, DEFAULT_VALUE);}该方法的参数提供你需要的一切:属性的阵列和android的索引位置:设置defaultValue,你必须检索。您必须实现此方法提取属性的默认值的原因是因为你必须指定的情况下,该值是不确定的属性的本地默认值。
保存和恢复首味道
就像在布局视图,您的喜好子类负责保存,并在情况下,活动或片段重新启动恢复其状态(当用户旋转屏幕等)。要正确保存和恢复您的喜好阶级的国家,你必须实现生命周期回调的onSaveInstanceState方法()和onRestoreInstanceState()。
您喜欢的状态是通过实现Parcelable接口的对象定义。 Android框架为您提供了这样一个对象作为起点来定义状态对象:Preference.BaseSavedState类。
要定义您的偏好类如何保存其状态时,你应该扩展Preference.BaseSavedState类。你需要重写短短的方法和定义CREATOR对象。
对于大多数应用程序,您可以复制以下实现,只是改变处理值,如果你偏好的子类可以节省不是整数的其他数据类型的线条。
private static class SavedState extends BaseSavedState { // Member that holds the setting's value // Change this data type to match the type saved by your Preference int value; public SavedState(Parcelable superState) { super(superState); } public SavedState(Parcel source) { super(source); // Get the current preference's value value = source.readInt(); // Change this to read the appropriate data type } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); // Write the preference's value dest.writeInt(value); // Change this to write the appropriate data type } // Standard creator object using an instance of this class public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { public SavedState createFromParcel(Parcel in) { return new SavedState(in); } public SavedState[] newArray(int size) { return new SavedState[size]; } };}与上述实施Preference.BaseSavedState的添加到您的应用程序(通常是你的偏好的子类的子类),你需要实现的onSaveInstanceState的()和onRestoreInstanceState()方法,为您偏好的子类。
例如:
@Overrideprotected Parcelable onSaveInstanceState() { final Parcelable superState = super.onSaveInstanceState(); // Check whether this Preference is persistent (continually saved) if (isPersistent()) { // No need to save instance state since it's persistent, // use superclass state return superState; } // Create instance of custom BaseSavedState final SavedState myState = new SavedState(superState); // Set the state's value with the class member that holds current // setting value myState.value = mNewValue; return myState;}@Overrideprotected void onRestoreInstanceState(Parcelable state) { // Check whether we saved the state in onSaveInstanceState if (state == null || !state.getClass().equals(SavedState.class)) { // Didn't save the state, so call superclass super.onRestoreInstanceState(state); return; } // Cast state to custom BaseSavedState and pass to superclass SavedState myState = (SavedState) state; super.onRestoreInstanceState(myState.getSuperState()); // Set this Preference's widget to reflect the restored state mNumberPicker.setValue(myState.value);}
更多相关文章
- IOS各项生命周期
- Android产品设计规范
- Android(安卓)开发解决APP在18:9,18.5:9,19:9,19:10尺寸的手机上不
- android 4.0以上设置wifi静态IP以及DNS的方法
- 应用基础
- 【Android】Android防止过快点击造成多次事件执行(防止按钮重复点
- [置顶] Android(安卓)自定义TabHost
- 最热的前100的Android应用程序已被黑客入侵
- Android全局异常处理(捕获异常,不弹出程序崩溃)