Android偏好设置(7)自定义Preference,和PreferenceDialog
Building a Custom Preference
The Android framework includes a variety of Preference subclasses that allow you to build a UI for several different types of settings. However, you might discover a setting you need for which there’s no built-in solution, such as a number picker or date picker. In such a case, you’ll need to create a custom preference by extending the Preference class or one of the other subclasses.
When you extend the Preference class, there are a few important things you need to do:
- Specify the user interface that appears when the user selects the settings.
- Save the setting's value when appropriate.
- Initialize the
Preferencewith the current (or default) value when it comes into view. - Provide the default value when requested by the system.
- If the
Preferenceprovides its own UI (such as a dialog), save and restore the state to handle lifecycle changes (such as when the user rotates the screen).
The following sections describe how to accomplish each of these tasks.
Specifying the user interface
If you directly extend the Preference class, you need to implement onClick() to define the action that occurs when the user selects the item. However, most custom settings extend DialogPreference to show a dialog, which simplifies the procedure. When you extend DialogPreference, you must callsetDialogLayoutResourcs() during in the class constructor to specify the layout for the dialog.
For example, here's the constructor for a custom DialogPreference that declares the layout and specifies the text for the default positive and negative dialog buttons:
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);
}
...
}
Saving the setting's value
You can save a value for the setting at any time by calling one of the Preference class's persist*() methods, such as persistInt() if the setting's value is an integer or persistBoolean() to save a boolean.
Note: Each Preference can save only one data type, so you must use the persist*() method appropriate for the data type used by your custom Preference.
When you choose to persist the setting can depend on which Preference class you extend. If you extendDialogPreference, then you should persist the value only when the dialog closes due to a positive result (the user selects the "OK" button).
When a DialogPreference closes, the system calls the onDialogClosed() method. The method includes a boolean argument that specifies whether the user result is "positive"—if the value is true, then the user selected the positive button and you should save the new value. For example:
@Override
protected void onDialogClosed(boolean positiveResult) {
// When the user selects "OK", persist the new value
if (positiveResult) {
persistInt(mNewValue);
}
}
In this example, mNewValue is a class member that holds the setting's current value. Calling persistInt()saves the value to the SharedPreferences file (automatically using the key that's specified in the XML file for this Preference).
Initializing the current value
When the system adds your Preference to the screen, it calls onSetInitialValue() to notify you whether the setting has a persisted value. If there is no persisted value, this call provides you the default value.
The onSetInitialValue() method passes a boolean, restorePersistedValue, to indicate whether a value has already been persisted for the setting. If it is true, then you should retrieve the persisted value by calling one of the Preference class's getPersisted*() methods, such as getPersistedInt() for an integer value. You'll usually want to retrieve the persisted value so you can properly update the UI to reflect the previously saved value.
If restorePersistedValue is false, then you should use the default value that is passed in the second argument.
@Override
protected 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);
}
}
Each getPersisted*() method takes an argument that specifies the default value to use in case there is actually no persisted value or the key does not exist. In the example above, a local constant is used to specify the default value in case getPersistedInt() can't return a persisted value.
Caution: You cannot use the defaultValue as the default value in the getPersisted*() method, because its value is always null when restorePersistedValue is true.
Providing a default value
If the instance of your Preference class specifies a default value (with the android:defaultValue attribute), then the system calls onGetDefaultValue() when it instantiates the object in order to retrieve the value. You must implement this method in order for the system to save the default value in the SharedPreferences. For example:
@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getInteger(index, DEFAULT_VALUE);
}
The method arguments provide everything you need: the array of attributes and the index position of theandroid:defaultValue, which you must retrieve. The reason you must implement this method to extract the default value from the attribute is because you must specify a local default value for the attribute in case the value is undefined.
Saving and restoring the Preference's state
Just like a View in a layout, your Preference subclass is responsible for saving and restoring its state in case the activity or fragment is restarted (such as when the user rotates the screen). To properly save and restore the state of your Preference class, you must implement the lifecycle callback methods onSaveInstanceState()and onRestoreInstanceState().
The state of your Preference is defined by an object that implements the Parcelable interface. The Android framework provides such an object for you as a starting point to define your state object: thePreference.BaseSavedState class.
To define how your Preference class saves its state, you should extend the Preference.BaseSavedStateclass. You need to override just a few methods and define the CREATOR object.
For most apps, you can copy the following implementation and simply change the lines that handle the value if your Preference subclass saves a data type other than an integer.
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];
}
};
}
With the above implementation of Preference.BaseSavedState added to your app (usually as a subclass of your Preference subclass), you then need to implement the onSaveInstanceState() andonRestoreInstanceState() methods for your Preference subclass.
For example:
@Override
protected 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;
} @Override
protected 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);
}
Android偏好设置(7)自定义Preference,和PreferenceDialog的更多相关文章
- Android的设置界面及Preference使用
一般来说,我们的APP都会有自己的设置页面,那么其实我们有非常简单的制作方法.老样子,先看效果图. 然后就是看源代码了. 第一步,先在res文件夹中新建一个xml文件夹,用来存放preferences ...
- Android偏好设置(2)为应用定义一个偏好设置xml
1.Defining Preferences in XML Although you can instantiate new Preference objects at runtime, you sh ...
- Android偏好设置(1)概述和Preferences简介
1.Overview Instead of using View objects to build the user interface, settings are built using vario ...
- Android偏好设置(6)应用和监听各偏好参数
Reading Preferences By default, all your app's preferences are saved to a file that's accessible fro ...
- Android偏好设置(5)偏好设置界面显示多个分组,每个分组也有一个界面
1.Using Preference Headers In rare cases, you might want to design your settings such that the first ...
- Android偏好设置(4)设置默认值
Setting Default Values The preferences you create probably define some important behaviors for your ...
- Android偏好设置(3)启动偏好设置后显示的界面PreferenceActivity和PreferenceFragment
Creating a Preference Activity To display your settings in an activity, extend the PreferenceActivit ...
- 【起航计划 031】2015 起航计划 Android APIDemo的魔鬼步伐 30 App->Preferences->Advanced preferences 自定义preference OnPreferenceChangeListener
前篇文章Android ApiDemo示例解析(31):App->Preferences->Launching preferences 中用到了Advanced preferences 中 ...
- MongoDB 读偏好设置中增加最大有效延迟时间的参数
在某些情况下,将读请求发送给副本集的备份节点是合理的,例如,单个服务器无法处理应用的读压力,就可以把查询请求路由到可复制集中的多台服务器上.现在绝大部分MongoDB驱动支持读偏好设置(read pr ...
随机推荐
- Java同步锁何时释放?
在测试java多线程中有关 “生产者和消费者” 这个经典问题的时候,写代码测试的时候,思考到一些问题(所以还是要动手,实践才能储真知啊), synchronize 同步锁何时释放,何时获得?重新获得锁 ...
- [Unit Testing] Mock an HTTP request using Nock while unit testing
When testing functions that make HTTP requests, it's not preferable for those requests to actually r ...
- crm使用soap删除下拉框
//C# 代码: //DeleteOptionSetRequest request = new DeleteOptionSetRequest(); //request.Name = "new ...
- leetcode笔记:Majority Element
一. 题目描写叙述 Given an array of size n, find the majority element. The majority element is the element t ...
- [libcurl]_[0基础]_[使用libcurl下载大文件]
场景: 1. 在Windows编程时, 下载http页面(html,xml)能够使用winhttp库,可是并非非常下载文件,由于会失败. 由此引出了WinINet库,无奈这个库的稳定性比較低,使用样例 ...
- 2016/3/24 ①数据库与php连接 三种输出fetch_row()、fetch_all()、fetch_assoc() ②增删改时判断(布尔型) ③表与表之间的联动 ④下拉菜单 ⑤登陆 三个页面
①数据库与php连接 图表 header("content-type:text/html;charset=utf-8"); //第一种方式: //1,生成连接,连接到数据库上的 ...
- 安卓输入子系统之inotify与epoll机制【学习笔记】【原创】
平台信息:内核:linux3.1.0系统:android5.0平台:tiny4412 作者:庄泽彬(欢迎转载,请注明作者) 说明: 韦老师的安卓视频学习笔记 一.在安卓的输入子系统中如何监听文件的产生 ...
- 《CMake实践》笔记二:INSTALL/CMAKE_INSTALL_PREFIX【转】
本文转载自:http://www.cnblogs.com/52php/p/5681751.html 四.更好一点的Hello World 没有最好,只有更好 从本小节开始,后面所有的构建我们都将采用 ...
- 主机与虚拟机互ping
1.设置虚拟机网络连接方式(如下图): 2.设置主机和虚拟机的ip为同一个网段,如主机ip:192.168.28.1,虚拟机ip:192.168.28.128 3.如果相互还是ping不通,就检查一下 ...
- bzoj1090 [SCOI2003]字符串折叠——区间DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1090 区间DP... 代码如下: #include<iostream> #inc ...