Android进阶——Preference详解之Preference系的基本应用(三)

引言

前面一篇文章Android进阶——Preference详解之Preference系的基本应用和管理(二)介绍了二级Preference的使用和特点,接下来进入系统给我提供的底级Preference的使用CheckBox选择项CheckBoxPreference、EditText编辑对话框EditTextPreference、列表选择ListPreference、多项选择MultiSelectListPreference、 开关选择SwitchPreference的应用和管理。以期大家能在学习的时候不仅仅只是会用,更应该知其然而知其所以然。

一、Preference系树形结构图

首先还是再来回顾下Preference系的树形结构图,加深下他们之间的继承关系。

二、DialogPreference系

DialogPreference是一个抽象类直接继承自Preference,它的独特之处在于它是基于Dialog的,也就是说但我们点击对应的DialogPreference系时是以Dialog形式展现的。系统给我们提供了以下几个它的子类:EditTextPreferenceListPreferenceMultiSelectListPreference

1、DialogPreference系的共性

我们都知道DialogPreference是基于Dialog的,当我们点击的时候会以对话框的形式显示出来,所以除了继承自Preference的属性之外也还新增了很多自己独有的属性和方法。

1.1、DialogPreference系独有属性

DialogPreference系独有属性 说明
android:dialogIcon 对话框的icon
android:dialogLayout dialog 的contentView 布局
android:dialogMessage 对话框的内容
android:dialogTitle 对话框的标题
android:negativeButtonText 对话框里的按钮1名称
android:positiveButtonText 对话框里的按钮2名称

1.2、DialogPreference独有的方法

这里只列出三个有用的回调方法,其他setter、gettter方法和其他方法由于篇幅问题就不列出了(下同)。

方法 说明
void onActivityDestroy() 与Activity的onDestory类似,其实就是PreferenceManager.OnActivityDestroyListener的回调方法
void onClick(DialogInterface dialog, int which) 当对话框里的按钮被点击时,可以通过which来判断点击的按钮,其实就是DialogInterface.OnClickListener的回调方法
void onDismiss(DialogInterface dialog) 当对话框消失后执行,其实就是DialogInterface.OnDismissListener的回调方法

2、DialogPreference系的应用与管理

1、EditTextPreference

EditTextPreference新增方法 说明
EditText getEditText() 获取显示在Dialog上的EditText
String getText() 获取对应SharedPreferences保存的值
<?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">
    <EditTextPreference
        android:key="key_prerence"
        android:title="Preferece Title"
        android:summary="Preference Summary"
        />
</PreferenceScreen>

2、ListPreference

ListPreference和其他Preference一样的机制,也是借助于SharedPreferences来实现存储和更新,特别之处在于SharedPreferences存储的是android:entryValues的值(即android:entryValues与key一一对应形成键值对),而显示到界面的是android:entries则与android:entryValues一一对应

2.1、ListPreference的特有属性

ListPreference新增属性 说明
android:entries 列表的显示项数据源
android:entryValues 列表实际保存至内部的值
android:defaultValue 这个属性不是特有的,但是有一点需要注意:这里设置的是android:entryValues里的值
android:dialogMessage 如果设置了这个属性,那么列表怎么会被覆盖掉

2.2、ListPreference的特有方法

ListPreference新增方法 说明
int findIndexOfValue(String value) 返回获取ListPreference中的实体内容的下标值
CharSequence[] getEntries() 返回当前Preference设置的entries集合(xml配置的字符串数据源)
CharSequence getEntry() 返回当前选中的entries值
CharSequence[] getEntryValues() 返回当前的entries对应的value集合(xml配置的字符串数据源)
CharSequence getSummary() 获取当前summary
String getValue() 获取key值

2.3、ListPreference应用

列表数据源字符数组:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <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>

ListPreference的xml文件:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <ListPreference
        android:icon="@mipmap/ic_launcher"
        android:title="ListPreference"
        android:summary="ListPreference summary"
        android:dialogIcon="@mipmap/ic_blue_launcher"
        android:dialogTitle="Favourite Games"
        android:key="key_listpreference"
        android:entries="@array/game"
        android:entryValues="@array/game_index"
        />
</PreferenceScreen>

PreferenceActivity的实现:

public class ListPreferenceActivity extends PreferenceActivity implements Preference.OnPreferenceChangeListener{
    private ListPreference preference;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.list_preference);
        init();
    }
    private void init(){
        preference= (ListPreference) findPreference("key_listpreference");
        ///preference.setOnPreferenceClickListener(this); ****点击事件已经被覆盖掉了****
        preference.setOnPreferenceChangeListener(this);
        // 设置summary为所选中的值列表值
        if(preference.getEntry()!=null) {
            preference.setSummary(preference.getEntry());//初始化时设置summary
        }
    }
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        /*newValue 返回的值是getEntries的值
        * 01-09 12:30:43.558 15872-15872/com.crazymo.prerencescreen D/TAG2: onPreferenceChange run1
        * 01-09 12:41:10.627 15872-15872/com.crazymo.prerencescreen D/TAG2: onPreferenceChange run2
        * */
        if(preference instanceof ListPreference) {
            ListPreference listPreference = (ListPreference) preference;//把preference这个Preference强制转化为ListPreference类型
            CharSequence[] entries = listPreference.getEntries();//获取ListPreference中的实体内容
            int index = listPreference.findIndexOfValue((String) newValue);//获取ListPreference中的实体内容的下标值
            listPreference.setSummary(entries[index]);//listPreference中的sumamry显示为当前ListPreference的实体内容中选择的
            Log.d("TAG2", "onPreferenceChange run"+newValue);
            Toast.makeText(ListPreferenceActivity.this,entries[index].toString(),Toast.LENGTH_LONG).show();
        }
        return true;
    }
}

3、MultiSelectListPreference

MultiSelectListPreference和ListPreference都是列表形式的DialogPreference,不同的是ListPreference提供单选列表,而在Android3.0之后可以通过MultiSelectListPreference来实现多选,所以他们的属性和方法都几乎是相同的,当然也包括使用基本语法,但是要注意一点由于要支持多选,所以MultiSelectListPreference的SharedPreferences保存的是集合set(我们应该有这个概念集合就是用于保存多个对象的),所以读取数据的时候处理稍显麻烦。

3.1、MultiSelectListPreference新增的方法

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)

3.2、MultiSelectListPreference应用

还是使用一样的数据源,一样的xml(把ListPreference改为MultiSelectListPreference其他不变)

public class MutilListPreferenceActivity extends PreferenceActivity implements OnPreferenceChangeListener {
    private MultiSelectListPreference preference;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.list_preference);
        preference= (MultiSelectListPreference) findPreference("key_listpreference");
        preference.setOnPreferenceChangeListener(this);
        initFromSharedPreferences();
    }
    private void initFromSharedPreferences(){
        String summary=null;
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        Set<String>options = prefs.getStringSet("key_listpreference", null);  //因不设置初始值,所以要进行null的判断
        if(options!=null) {
            CharSequence[] extras = preference.getEntries();
            for (String op : options) {
                int index = preference.findIndexOfValue(op);
                if (summary==null) {
                   summary="";
                }
                summary = summary + extras[index];            }
            preference.setSummary(summary);
        }
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        if(preference instanceof MultiSelectListPreference) {
            String summary=null;
            MultiSelectListPreference multiSelectListPreference=(MultiSelectListPreference)preference;
            CharSequence[] extras =  multiSelectListPreference.getEntries();

            Set<String> options=(Set<String>)newValue;
            for (String op : options){
                int index = multiSelectListPreference.findIndexOfValue(op);
                Log.d("TAG2", op + extras[index]);
                if(summary==null) {
                    summary="";
                }
                summary = summary + extras[index];
            }
            Log.d("TAG2","onPreferenceChange:::"+summary);
            multiSelectListPreference.setSummary(summary);
        }
        return true;
    }
}
/**Log
*01-10 10:31:57.233 6089-6089/com.crazymo.prerencescreen D/TAG2: 1Dota2
01-10 10:31:57.234 6089-6089/com.crazymo.prerencescreen D/TAG2: 2NBA2K10
01-10 10:31:57.234 6089-6089/com.crazymo.prerencescreen D/TAG2: onPreferenceChange:::Dota2NBA2K10
*/

三、TwoStatePreference系

TwoStatePreference也是一个抽象类,作用如字面意思。是基于两种可选状态的首选项基类,他没有新增独特的属性,全都是继承上级,在SharedPreferences里通过维护一个布尔值(checked时为true)来设置当前状态的启用和禁止的一种Preference。Android也为我们提供了两种:CheckBox选择项CheckBoxPreference和 开关选择SwitchPreference供我们直接使用。

1、TwoStatePreference的共性

TwoStatePreference系独有方法 说明
CharSequence getSummaryOff() 获取unchecked状态下summary的值
CharSequence getSummaryOn() 获取checked状态下summary的值
boolean isChecked() 获取是否checked
void setChecked(boolean checked) 设置checked状态
void setSummaryOff 设置unchecked下summary的值,可以通过字符串id和字符串
void setSummaryOn 设置checked下summary的值,可以通过字符串id和字符串

2、TwoStatePreference的应用与管理

1、CheckBoxPreference

1.1、CheckBoxPreference新增的属性

CheckBoxPreference新增属性 说明
android:summaryOff uncheck时的summary
android:summaryOn check时的summary

1.2、CheckBoxPreference应用

res/xml/widget_layout.xml

<?xml version="1.0" encoding="utf-8"?>
    <CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/checkbox"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:button="@mipmap/ic_bt_config"
        android:clickable="false"
        android:focusable="false" />
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference
        android:icon="@mipmap/ic_launcher"
        android:key="key_checkboxprefs"
        android:title="CheckBoxPreference"
        android:summary="CheckBoxPreference summary"
        android:summaryOff="Summary off"
        android:summaryOn="On Summary"
        android:order="10"
        />
    <CheckBoxPreference
        android:icon="@mipmap/ic_blue_launcher"
        android:key="key_checkboxprefs2"
        android:title="CheckBoxPreference2"
        android:summary="CheckBoxPreference2 summary"
        android:summaryOff=" Off Summary2"
        android:summaryOn="On Summary2"
        android:order="1"
        android:widgetLayout="@xml/widget_layout"
        />
</PreferenceScreen>

每次点击的时候先执行onChange再执行onClick

01-10 11:16:56.459 31292-31292/com.crazymo.prerencescreen D/TAG2: true
01-10 11:16:56.464 31292-31292/com.crazymo.prerencescreen D/TAG2: CheckBox Clicked!!
01-10 11:36:19.660 31292-31292/com.crazymo.prerencescreen D/TAG2: false
01-10 11:36:19.662 31292-31292/com.crazymo.prerencescreen D/TAG2: CheckBox Clicked!!

2、SwitchPreference

2.1、SwitchPreference新增属性

CheckBoxPreference新增属性 说明
android:summaryOff uncheck时的summary
android:summaryOn check时的summary
android:switchTextOff
android:switchTextOn

2.2、SwitchPreference应用

每次点击的时候先执行onChange再执行onClick

01-10 11:47:55.554 12915-12915/com.crazymo.prerencescreen D/TAG2: true
01-10 11:47:55.559 12915-12915/com.crazymo.prerencescreen D/TAG2: SwitchPrefeence Clicked

小结

通过这两篇文章我们终于把Preference的应用和一些简单原理给弄清楚了,其实这并不需要我们去背语法或者api什么的,我们要从原理去理解,从他们的结构关系去理解,究其根本。Preference只不过是把自己的key作为SharedPreferences里的key保存数据,进而再再次进入界面的时候由Activity去自动读取并刷新UI,不同的Preference保存的SharedPreferences格式不一样,比如说TwoStatePreference保存的是boolean的键值对,ListPreference则保存普通的字符串键值对;MultiSelectListPreference由于要保存多组数据则采取的是保存set集合等等,原理可以归结为两步:SharedPreferences的数据保存和PreferenceActivity读取SharedPrefences的数据并更新。

时间: 2024-10-08 23:46:52

Android进阶——Preference详解之Preference系的基本应用(三)的相关文章

Android进阶——Preference详解之Preference系的基本应用和管理(二)

引言 前面一篇文章Android进阶--Preference详解之初识Preference及Preference系(一)简单描述下了Preference的家族构成和基本知识,相信对于Preference早已不会陌生,肯定也跃跃欲试了吧,这篇文章就给大家总结下Preference.PreferenceActivity.PreferenceGroup.RingtonePreference的普通应用和管理,还有通过一些测试来验证一些机制和原理. 一.PreferenceActivity 1.Prefe

Android进阶——Fragment详解之操作原理(三)

引言 前一篇文章总结了Fragment 的基本概念和基本的用法,相信大家也能够掌握一些知识了,但是对于一些操作可能还是不知其所以然,说实话曾经很长一段时间为也是晕乎乎的,后来才慢慢重视去学习了解,才略知一二,遂分享之. 一.管理Fragement所涉及到的关键类 应用Fragment的过程中涉及到的关键类主要有:FragmentManager和.FragmentManagerImpl.FragmentTransaction和BackStackRecord等. 二.Fragment操作原理详述 1

android屏幕适配详解

android屏幕适配详解 官方地址:http://developer.android.com/guide/practices/screens_support.html 一.关于布局适配建议 1.不要使用绝对布局 2.尽量使用match_parent 而不是fill_parent . 3.能够使用权重的地方尽量使用权重(android:layout_weight) 4.如果是纯色背景,尽量使用android的shape 自定义. 5.如果需要在特定分辨率下适配,可以在res目录上新建layout

Android 四大组件 详解

[置顶] Android四大组件详解 分类: Android四大组件2013-02-09 16:23 19411人阅读 评论(13) 收藏 举报 Android开发 注:本文主要来自网易的一个博主的文章,经过阅读,总结,故留下文章在此 Android四大基本组件介绍与生命周期 Android四大基本组件分别是Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器. 一:了解四大基本组件 Activity : 应用程序中,一个

Android权限Permission详解

android.permission.EXPAND_STATUS_BAR 允许一个程序扩展收缩在状态栏,Android开发网提示应该是一个类似Windows Mobile中的托盘程序 android.permission.FACTORY_TEST 作为一个工厂测试程序,运行在root用户 android.permission.INSTALL_PACKAGES 允许一个程序安装packages android.permission.INTERNAL_SYSTEM_WINDOW 允许打开窗口使用系统

Android SlidingMenu 使用详解

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/36677279 很多APP都有侧滑菜单的功能,部分APP左右都是侧滑菜单~SlidingMenu 这个开源项目可以很好帮助我们实现侧滑功能,如果对SlidingMenu 还不是很了解的童鞋,可以参考下本篇博客.将侧滑菜单引入项目的方式很多中,本博客先通过例子介绍各种引入方式,然后给大家展示个实例:主布局ViewPager,左右各一个侧滑菜单的用法,差不多已经能满足大部分应用的需求

Android中Context详解 ---- 你所不知道的Context

转载至 :http://blog.csdn.net/qinjuning 前言:本文是我读<Android内核剖析>第7章 后形成的读书笔记 ,在此向欲了解Android框架的书籍推荐此书. 大家好,  今天给大家介绍下我们在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中 时刻的在与它打交道,例如:Service.BroadcastReceiver.Activity等都会利用到Context的相关方法 : 说它陌生,完全是 因为我们真正的不懂Context

Android相机开发详解(一)

Android相机开发详解(一) 请支持原创,尊重原创,转载请注明出处:http://blog.csdn.net/kangweijian(来自kangweijian的csdn博客) Android相机开发能够实现打开相机,前后摄像头切换,摄像预览,保存图片,浏览已拍照图片等相机功能. Android相机开发详解(一)主要实现打开相机,摄像预览,前后置摄像头切换,保存图片等四个功能. Android相机开发详解(二)主要实现翻页浏览相片,触控缩放浏览图片,删除图片,发送图片等四个功能. Andro

Android中Context详解 ---- 你所不知道的Context (转载)

Android中Context详解 ---- 你所不知道的Context (转载) http://blog.csdn.net/qinjuning 大家好,  今天给大家介绍下我们在应用开发中最熟悉而陌生的朋友-----Context类 ,说它熟悉,是应为我们在开发中 时刻的在与它打交道,例如:Service.BroadcastReceiver.Activity等都会利用到Context的相关方法 : 说它陌生,完全是 因为我们真正的不懂Context的原理.类结构关系.一个简单的问题是,一个应用