当前位置: 首页 > backend >正文

Preference 系统自带的偏好设置页面解析

导读

最近做项目无意中看到Perference类,发现Android系统设置就是用这个实现,感觉自己以前写的设置页面都白写了,而且还浪费时间

关于设置页面的介绍这里就不详细介绍了,官方文档已经写得很详细,官方推荐我们使用在XML文件中声明Preference类的各种子类构建设置页面,而不是使用View对象构建用户界面

下面是我的学习总结,希望能辅助到小白学习吧..!(赶时间直接想用的跳到Preference简单使用)

Google 官方文档链接

官方文档Preference列出来的类结构树

这里写图片描述

==补充说明==

  1. Preference类提供了SharedPreference用于保存或读取数据.key属性作为SharedPreference的键.最终保存在data/data/包名/shared_prefs文件下.
  2. 由于应用的设置UI使用的是Preference对象构建而成,隐藏需要专门的Activity或Fragment子类显示列表设置.
    • 如果应用版本低于Android 3.0(API 10),必需将Activity构建为PreferenceActivity类的扩展
    • 对于Android 3.0 以上的版本,在传统的Activitiy中使用PreferenceFragment来显示

在data/data/包名/shared_prefs 导出文件如下


<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map><!--ListPreference在SharedPreference保存的状态--><string name="key_List">1</string><!--MultiSelectListPreference在SharedPreference保存的状态--><set name="key_MultiSelectList"><string>1</string><string>2</string></set><!--EditTextPreference在SharedPreference保存的状态--><string name="key_EditText">fedhfghhfdghdffghdfgh</string><!--CheckBoxPreference在SharedPreference保存的状态--><boolean name="key_CheckBoxPreference" value="true" /><!--RingtonePreference在SharedPreference保存的状态--><string name="key_RingtonePreference">content://media/internal/audio/media/6</string></map>

PreferenceScreen

  1. PreferenceScreen作为PreferenceActivity基本布局的根容器,类似普通布局的各种Layout
  2. 可以通过xml方式或者通过createPreferenceScreen(Context)方式来构造PreferenceScreen
  3. PreferenceScreen可以被PreferenceCategory嵌套,也可以PreferenceScreen嵌套PreferenceScreen,将通过新开屏幕显示

PreferenceScreenxmlns:android="http://schemas.android.com/apk/res/android"android:key="first_preferencescreen"><CheckBoxPreferenceandroid:key="wifi enabled"android:title="WiFi" /><PreferenceScreenandroid:key="second_preferencescreen"android:title="WiFi settings"><CheckBoxPreferenceandroid:key="prefer wifi"android:title="Prefer WiFi" />... other preferences here ...</PreferenceScreen>
</PreferenceScreen> 

PreferenceCategory

通常作为二级容器嵌套在PreferenceScreen里提供分组的作用,类似数据库SQL中的group by.

PreferenceCategory效果图

EditTextPreference(输入框Dialog)

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"><!--EditText getEditText()  获取显示在Dialog上的EditText--><!--String getText()    获取对应SharedPreferences保存的值--><!--String setText()    设置对应SharedPreferences保存的值--><EditTextPreference
        android:dialogTitle="ETPreference"android:key="key_EditText"android:summary="EditTextPreference summary"android:title="EditTextPreference"/></PreferenceScreen>

这里写图片描述

ListPreference(单选框列表Dialog)

<!--android:entries 列表的显示项数据源--><!--android:entryValues 列表实际保存至内部的值--><!--android:defaultValue    这个属性不是特有的,但是有一点需要注意:这里设置的是android:entryValues里的值--><!--android:dialogMessage   如果设置了这个属性,那么列表怎么会被覆盖掉--><!--int findIndexOfValue(String value)  返回获取ListPreference中的实体内容的下标值--><!--CharSequence[] getEntries() 返回当前Preference设置的entries集合(xml配置的字符串数据源)--><!--CharSequence getEntry() 返回当前选中的entries值--><!--CharSequence[] getEntryValues() 返回当前的entries对应的value集合(xml配置的字符串数据源)--><!--CharSequence getSummary()   获取当前summary--><!--String getValue()   获取key值--><ListPreference
        android:dialogTitle="List"android:entries="@array/game"android:entryValues="@array/game_index"android:key="key_List"android:summary="ListPreference summary"android:title="ListPreference"/>

这里写图片描述

MultiSelectListPreference(多选框列表Dialog)

<!--MultiSelectListPreference新增方法   说明--><!--int findIndexOfValue(String value)  返回获取ListPreference中的实体内容的下标值--><!--CharSequence[] getEntries() 返回当前Preference 设置的entries集合(xml配置的字符串数据源)--><!--CharSequence[] getEntryValues() 返回当前的entries对应的value集合(xml配置的字符串数据源)--><!--Set getValues() 返回当前选中的values,SharedPreference的--><!--void setEntries(int entriesResId)--><!--void setEntries(CharSequence[] entries)--><!--void setEntryValues(CharSequence[] entryValues)--><!--void setEntryValues(int entryValuesResId)--><!--void setValues(Set values)--><MultiSelectListPreference
        android:dialogTitle="MultiSelectList"android:entries="@array/game"android:entryValues="@array/game_index"android:key="key_MultiSelectList"android:summary="MultiSelectListPreference summary"android:title="MultiSelectListPreference"/>

这里写图片描述

res/values/array.xml定义

<?xml version="1.0" encoding="utf-8"?>
<resources><!--ListPreference 要显示的数据--><string-array name="game"><item>Dota</item><item>Dota2</item><item>NBA2K10</item><item>FIFA2K10</item></string-array><string-array name="game_index"><item>0</item><item>1</item><item>2</item><item>3</item></string-array></resources>

CheckBoxPreference

    <!--android:widgetLayout 选中框布局--><!--android:summaryOff  uncheck时的summary--><!--android:summaryOn   check时的summary--><CheckBoxPreference
        android:icon="@mipmap/ic_launcher"android:key="key_checkbox_preference"android:order="10"android:summary="CheckboxPreference summary"android:summaryOff="Summary off"android:summaryOn="On Summary"android:title="CheckBoxPreference"/>

这里写图片描述

SwitchPreference

<!--android:summaryOff  uncheck时的summary--><!--android:summaryOn   check时的summary--><!--android:switchTextOff 处于off状态,switch使用的文本--><!--android:switchTextOn--><SwitchPreference
        android:key="key_SwitchPreference"android:order="1"android:summary="SwitchPreference summary"android:summaryOff="Off "android:summaryOn="On"android:switchTextOff="关"android:switchTextOn="开"android:title="SwitchPreference"android:widgetLayout="@layout/activity_show"/>

这里写图片描述

RingtonePreference

RingtonePreference起作用就是供我们选择系统铃声的

特有属性说明
android:ringtoneType铃声类型:ringtone(1)、notification(2)、all(7)、alarm(4)
android:showDefault布尔值是否显示默认铃声
android:showSilent布尔值是否显示静音

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"android:key="using_categories_in_root_screen"android:summary="Using Preference Categories"android:title="Categories"><RingtonePreference
        android:key="key_prerence"android:title="RingPreferece Title"android:summary="RingPreference Summary"/></PreferenceScreen>

这里写图片描述

自定义Preference(主要是自定义控件方式)

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

Preference监听事件的回调接口和方法

一、监听某个Preference被点击回调

findPreference("Preference").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {@Overridepublic boolean onPreferenceClick(Preference preference) {Toast.makeText(getActivity(), "Preference 被点击了", Toast.LENGTH_SHORT).show();return true;}});

二、监听任意首选项状态发生改变时立即收到通知

//强引用方式创建监听器,防止监听器被垃圾回收掉
//这个回调只有状态发生改变才会被调用SharedPreferences.OnSharedPreferenceChangeListener listener =new SharedPreferences.OnSharedPreferenceChangeListener() {public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {// listener implementationif (key.equals("key_EditTextPreference")) {Preference connectionPref = findPreference(key);// Set summary to be the user-description for the selected valuePreference key_EditTextPreference = findPreference("key_EditTextPreference");key_EditTextPreference.setSummary(sharedPreferences.getString(key, "") + "");}}};//生命周期管理,在onResume()和onPause()回调期间分别注册和注销@Override
protected void onResume() {super.onResume();getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(listener);
}@Override
protected void onPause() {super.onPause();getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(listener);
}

Preference简单使用

一、在res/xml/目录下创建为根节点的xml文件,并按照上述的XXXPreference设置属性

 <PreferenceCategory
        android:title="PreferenceCategory"><!--android:widgetLayout  修改Preference里的子布局--><!--android:layout 修改Preference的布局--><Preference
            android:icon="@mipmap/ic_launcher_round"android:summary="Open otherActivity (Preference)"android:title="Open otherActivity"></Preference></PreferenceCategory><!--嵌套PreferenceScreen 会再打开一个子屏幕--><!--可以使用extra给intent标签加参数来传递参数实现意图 会再打开一个子屏--><PreferenceScreen
        android:summary="Open the Web (Preference)"android:title="嵌套PreferenceScreen Open the Web "><Preference
            android:title="Open the Web (Preference)"><intent
                android:action="android.intent.action.VIEW"android:data="http://www.hao123.com"/></Preference></PreferenceScreen><!--选择系统铃声的--><!--android:ringtoneType    铃声类型:ringtone、notification、all、alarm--><!--android:showDefault 布尔值是否显示默认铃声--><!--android:showSilent  布尔值是否显示静音--><RingtonePreference
        android:key="key_RingtonePreference"android:ringtoneType="all"android:showDefault="true"android:showSilent="true"android:summary="RingPreference (铃声设置)"android:title="RingtonePreference"/><!--android:order 首选项的顺序(较低的值在前面)--><EditTextPreference
        android:key="key_EditTextPreference"android:order="1"android:summary="EditTextPreference 输入框"android:title="EditTextPreference"/><Preference
        android:key="key_Preference"android:summary="please Click me"android:title="Preference Click Test"/>

二、初始化PreferenceActivity或PreferenceFragment,按需设置相关监听器

public class NormalPreferenceFragment extends PreferenceFragment  {private RingtonePreference mKey_ringtonePreference;private Preference         mKey_preference;@Overridepublic void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);//引入Preference XML文件addPreferencesFromResource(R.xml.normal_preference);mKey_ringtonePreference = (RingtonePreference) findPreference("key_RingtonePreference");int ringtoneType = mKey_ringtonePreference.getRingtoneType();boolean showDefault = mKey_ringtonePreference.getShowDefault();boolean showSilent = mKey_ringtonePreference.getShowSilent();mKey_preference = findPreference("key_Preference");mKey_preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {@Overridepublic boolean onPreferenceClick(Preference preference) {Toast.makeText(getActivity(), "Preference 被点击了", Toast.LENGTH_SHORT).show();return true;}});}SharedPreferences.OnSharedPreferenceChangeListener listener =new SharedPreferences.OnSharedPreferenceChangeListener() {public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {// listener implementationif (key.equals("key_EditTextPreference")) {Preference connectionPref = findPreference(key);// Set summary to be the user-description for the selected valuePreference key_EditTextPreference = findPreference("key_EditTextPreference");key_EditTextPreference.setSummary(sharedPreferences.getString(key, "") + "");}}};@Overridepublic void onResume() {super.onResume();//注册监听getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(listener);}@Overridepublic void onPause() {super.onPause();//取消监听getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(listener);}}

首选项标头使用

我们知道可以用嵌套的PreferenceScreen元素构建子屏幕,但在Android 3.0(API 10)以上的版本,更建议我们我们使用”标头”功能,好处是在大屏幕运行时,会自动提供双窗格布局

一、创建标头XML文件

<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"><header
        android:fragment="zs.xmx.last.NormalPreferenceFragment"android:summary="NormalPreferenceFragment"android:title="NormalPreferenceFragment"><!-- key/value pairs can be included as arguments for the fragment. --><extra
            android:name="headers_key"android:value="preference-headers 携带的值"/></header><header
        android:fragment="zs.xmx.last.DialogPreferenceFragment"android:summary="DialogPreferenceFragment"android:title="DialogPreferenceFragment"/><header
        android:fragment="zs.xmx.last.TwoStatePreferenceFragment"android:summary="TwoStatePreferenceFragment"android:title="TwoStatePreferenceFragment"/><header
        android:fragment="zs.xmx.last.CustomPreferenceFragment"android:summary="CustomPreferenceFragment"android:title="CustomPreferenceFragment"/></preference-headers>

二、显示标头


/*** 使用标头,要继承PreferenceActivity,重写onBuildHeaders()和isValidFragment()*/
public class SettingPreferenceActivity extends PreferenceActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (hasHeaders()) {  //如有header,则在最下面加一个button。本例无论平板还是phone,都返回trueButton button = new Button(this);button.setText("Exit");setListFooter(button);}}@Overridepublic void onBuildHeaders(List<Header> target) {super.onBuildHeaders(target);loadHeadersFromResource(R.xml.preference_heads, target);}/*** API 19以上的安全机制,需要重写isValidFragment()* <p>* 1.直接return true* <p>* 2.return [YOUR_FRAGMENT_NAME].class.getName().equals(fragmentName);** @param fragmentName* @return*/@Overrideprotected boolean isValidFragment(String fragmentName) {return true;}

这里写图片描述

==Preference注意事项==

并非我们第一次打开相应界面之后就会自动创建对应的SharedPreferences文件,而是在我们改变了原有状态时候

并非所有的Preference及其子类都会创建,仅仅针对需要记录状态的Preference.

使用PreferenceActivity时,setContentView()方法的layout文件里必须包含id为android.R.id.list的listView,否则会报E/AndroidRuntime: Caused by: Java.lang.RuntimeException: Your content must have a ListView whose id attribute is ‘android.R.id.list’,再调用addPreferencesFromResource来完成Preference界面的构建;建议直接调用addPreferencesFromResource方法.

扩展:

使用Intent

在某些情况下,您可能需要首选项来打开不同的 Activity(而不是网络浏览器等设置屏幕)或查看网页.要在用户选择首选项时调用 Intent,请将 元素添加为相应 元素的子元素.


//使用首选项打开网页,属性与我们Activity使用Intent类似<Preference android:title="@string/prefs_web_page" ><intent android:action="android.intent.action.VIEW"android:data="http://www.example.com" />
</Preference>

保存和恢复首选项的状态

  • 类似Activity的横竖屏切换恢复状态,Preference 子类也负责保存并恢复其状态.要正确保存并恢复 Preference 类的状态,您必须实现生命周期回调方法 onSaveInstanceState() 和 onRestoreInstanceState().

  • Preference 的状态由实现 Parcelable 接口的对象定义.Android 框架为您提供此类对象,作为定义状态对象(Preference.BaseSavedState 类)的起点.

  • 要定义 Preference 类保存其状态的方式,您应该扩展 Preference.BaseSavedState 类.您只需重写几种方法并定义 CREATOR 对象.

  • 对于大多数应用,如果 Preference 子类保存除整型数以外的其他数据类型,则可复制下列实现并直接更改处理 value 的行.

private static class SavedState extends BaseSavedState {// Member that holds the setting's value// Change this data type to match the type saved by your Preferenceint value;public SavedState(Parcelable superState) {super(superState);}public SavedState(Parcel source) {super(source);// Get the current preference's valuevalue = source.readInt();  // Change this to read the appropriate data type}@Overridepublic void writeToParcel(Parcel dest, int flags) {super.writeToParcel(dest, flags);// Write the preference's valuedest.writeInt(value);  // Change this to write the appropriate data type}// Standard creator object using an instance of this classpublic 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 实现添加到您的应用(通常,作为 Preference 子类的子类),则需要为 Preference 子类实现 onSaveInstanceState() 和 onRestoreInstanceState() 方法。

@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 statereturn superState;}// Create instance of custom BaseSavedStatefinal SavedState myState = new SavedState(superState);// Set the state's value with the class member that holds current// setting valuemyState.value = mNewValue;return myState;
}@Override
protected void onRestoreInstanceState(Parcelable state) {// Check whether we saved the state in onSaveInstanceStateif (state == null || !state.getClass().equals(SavedState.class)) {// Didn't save the state, so call superclasssuper.onRestoreInstanceState(state);return;}// Cast state to custom BaseSavedState and pass to superclassSavedState myState = (SavedState) state;super.onRestoreInstanceState(myState.getSuperState());// Set this Preference's widget to reflect the restored statemNumberPicker.setValue(myState.value);
}

总结:

本篇到这里就完结了,喜欢的同学欢迎关注,后续会不断更新文章,也欢迎评论,支出错误,共同进步

http://www.xdnf.cn/news/11863.html

相关文章:

  • android中的TextWatcher的应用
  • Android应用获取root权限,修改系统文件
  • CentOS搭建并配置Nexus3记录
  • 干货整理:电脑监控软件都有哪些,哪款好用( 六大好用监控电脑软件推荐)
  • gps wifi信号测试软件,搜星+WiFi+EMI 导航平板信号性能横评
  • vb与EXCEL的连接
  • 由于找不到d3dx9_39.dll,无法继续执行代码的5种解决方法
  • 串口数据转以太网
  • Java入门基础,Java知识点总结合集
  • 迅雷老版本下载地址
  • 【学术相关】最新整理!绝对不能错过的130个学术网站和26个科研工具
  • OA系统:一文读懂OA系统,内附优秀OA界面。
  • nginx配置文件特殊字符说明
  • python实现抖音上比较火的罗盘时钟
  • 逆向工程入门学习(FreeBuf)
  • 黑马程序员 JavaScript
  • Iocomp Crack和ProEssentials Crack
  • 百度竞价点击器_百度竞价如何屏蔽恶意点击
  • Windows 7 RC十大功能的详细介绍以及改进方法
  • 【推荐】10个网站分类目录提交地址
  • linux下清理信号量,Linux下进程间通信方式——信号量(Semaphore)
  • JAVAscript的发展及八大数据类型
  • win10系统魔兽世界无法连接服务器地址,win10系统无法更新魔兽世界提示正在等待另一项安...
  • 罗马音平假字复制_罗马音平假名和片假名大全ID,罗马音平假名和片假名大全复制中文[多图]...
  • index of 的高级搜索命令
  • 对ROS局部运动规划器Teb的理解
  • 弘辽科技:淘宝怎么增加手淘访客?有什么技巧?
  • 153:vue+openlayers 设定修改图层的透明度
  • 【转】ACM竞赛和算法相关
  • Android版xx助手之天天酷跑外挂具体分析