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



引言

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

一、PreferenceActivity

1、PreferenceActivity概述

PreferenceActivity是一个抽象类,继承于ListActivity,以列表形式视图来展现界面,加载的整个View也是基于ListActivity中那个ListView的,其最主要的优势在于添加Preference后可让其状态持久化储存(通过SharedPreferences,一般存储在/data/data//shared_prefs文件夹下的默认名为“app package name”+”_preferences.xml”的文件里),比如说用户勾选CheckBox后退出应用,下一次进入到这一界面时候,对应的是CheckBox依然是被勾选状态,如果要实现这样的机制,我们自己也可以实现,但是没有必要,因为Android已经替我们实现了,就是我们的这一系列的主角——Preference,Preference会自动地替我们去保存这些状态对应的值到对应的SharedPreferences文件里,而当我们每次启动的时候Acitivity(PreferenceActivity)会自动根据key去获取相关数据,完成用户界面的更新。我们手机当中的系统设置就是及其典型的Preference的应用,也正是由于工作中需要去客制化Settings,才有了这一系列的文章。
这里写图片描述
上图是我们定制的Settings模块中的对应的部分SharedPreferences。关于Preference对应的SharedPreferences往往很容易被我们忽视两点

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

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

2、PreferenceActivity的初始化

PreferenceActivity其实和普通的Activity本质上来说区别不大,只不过多了些自动去读取SharedPrefrences的值来更新界面和其他一些逻辑,所以初始化本质上来说并无很大的区别,但是与普通Activity的layout不同,PreferenceActivity的layout我们可以理解成为两个部分:其他View和一个id为android.R.id.list的ListView,那么我们可以理解成为当我们在onCreate方法里先调用setContentView完成整个Activity的View的构建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方法。

1、继承PreferenceActivity实现具体业务类,重写相关生命周期方法

public class MainActivity extends PreferenceActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            addPreferencesFromResource(R.xml.demo_preference);
        }
        ...
    }
 
 

    2、通过addPreferencesFromResource(xml资源id)加载静态xml资源文件 或者 完全通过代码构造对象再动态添加

    res文件夹下新建xml文件夹,再在xml文件中新建对应的xml资源,xml资源类似我们在使用普通Activity时的layout文件,PreferenceActivity独特之处在于并不是使用普通的layout文件,而是使用res下xml文件夹下的xml资源文件

    res/xml/demo_preference.xml

    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
        <CheckBoxPreference
            android:key="key_checkbox_preference"
            android:summary="Some summay for CheckBoxPreference"
            android:title="The Title Of CheckBoxPreference" />
    </PreferenceScreen>
     
     

      也可通过代码去构造对象,添加容器之后再调用setPreferenceScreen(PreferenceScreen preferenceScreen)把容器对象设置到Activity上

      private void createPreference(){
              PreferenceScreen preferenceScreen = this.getPreferenceManager().createPreferenceScreen(this);//先构建PreferenceScreen对象得到一个布局容器
              this.setPreferenceScreen(preferenceScreen);//设置容器
              CheckBoxPreference checkBoxPreference=new CheckBoxPreference(this);//构建一个子Preference,待添加到容器中
              checkBoxPreference.setKey(CHECKBOXPRERENCE_KEY);//设置key
              checkBoxPreference.setTitle("The Title Of CheckBoxPreference");//设置title
              checkBoxPreference.setSummary("Some summay for CheckBoxPreference");
              preferenceScreen.addPreference(checkBoxPreference);//添加到容器中
          }
       
       

        二、Preference的使用

        前一篇文章我们讲述了Preference家族的基类(接下来我们所要介绍的其他子类Preference一定是继承了他的所有属性也可以理解成都是在继承他所展示的UI效果及交互功能的基础上升级的)而且Preference可以实例化,那么我们就可以把他看成对应的一个组件,其实和我们熟悉的TextView一样,所以我们需要使用的时候第一步肯定是先得到他的对象——而构造对象我们都可以通过两种方式:通过其对应的构造方法或者其他方法通过xml映射(或许说法不够准确),接着第二步PreferenceActivity的初始化,再接着根据业务设置相关监听。

        1、构造Preference容器和Preference对象

        前面Android进阶——Preference详解之初识Preference及Preference系(一)已经讲过PreferenceScreen只能作为top-level节点,而构造对象我们都可以通过两种方式:通过其对应的构造方法或者其他方法通过映射xml(或者讲法不够准确)

        res/xml/test_preference.xml

        <?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">
            <Preference
                android:key="key_prerence"
                android:title="Preferece"
                android:summary="Preference Demo"
                />
        </PreferenceScreen>
         
         

          2、初始化PreferenceActivity和设置相关监听

          常见的Preference的事件有两个:setOnPreferenceClickListeneronPreferenceChange

          • 设置Preference点击监听
           preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                      @Override
                      public boolean onPreferenceClick(Preference preference) {
                          //当接收到Click事件之后触发
                          return true;
                      }
                  });
           
           
            • 设置Preference对应的SharedPrefernces值监听
            preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                        @Override
                        public boolean onPreferenceChange(Preference preference, Object newValue) {
                            //如果值改变了我们可以通过监听这个事件来处理
                            return true;
                        }
                    });
             
             
              @Override
                  protected void onCreate(Bundle savedInstanceState) {
                      super.onCreate(savedInstanceState);
                      setContentView(R.layout.activity_main);//activity_main里必须存在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(R.xml.test_preference);
                      mContext=getApplicationContext();
                      preference=findPreference(PREFERENCE_KEY);
                      preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                          @Override
                          public boolean onPreferenceChange(Preference preference, Object newValue) {
                              //如果值改变了我们可以通过监听这个事件来获取新值
                              Toast.makeText(mContext, String.format("Preference的值为%s", newValue),Toast.LENGTH_LONG).show();
                              return true;
                          }
                      });
                      //设置Preference的点击事件监听
                      preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                          @Override
                          public boolean onPreferenceClick(Preference preference) {
                              //当接收到Click事件之后触发
                              Toast.makeText(mContext, "Preference Clicked",Toast.LENGTH_LONG).show();
                              return true;
                          }
                      });
                  }
               
               

                这里写图片描述

                3、Preference的常用xml属性

                xml属性说明
                android:iconPreference的icon
                android:summary副标题、说明(小字体显示)
                android:title标题
                android:key对应的SharedPrefrences的key值
                android:layoutPreferenceActivity的布局文件即如果设置了这个属性则会覆盖原来的UI
                android:fragment应用在PreferenceActivity中时,当用户点击这个Preference时,启动一个新的Fragment
                android:enabled设置Preference是否可用,false阴影状态不可操作
                android:orderPreference的排序,整数类型如”100”
                android:persistenttrue时,系统会帮助我们去保存该设置,即使重启后依然能记忆之前的设置,这也是所谓的持久化 。这里 将 android:persistent设置为False,表明不需要让系统去做持久化,开发者系统通过自己的方式去实现持久化。
                android:selectablePreference是否可选,false可以点击但无响应
                android:shouldDisableView当View disabled的时候是否Preference也一样Disabled.
                android:widgetLayout自定义Preference用到给子Preference定义布局。
                <?xml version="1.0" encoding="utf-8"?>
                <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
                    android:title="PreferenceScreen">
                <PreferenceCategory
                    android:key="key_prerence"
                    android:summary="Preference Categories Summary"
                    android:title="Preference Categories">
                    <CheckBoxPreference
                        android:icon="@mipmap/ic_launcher"
                        android:key="key_chkpreference"
                        android:title="CheckBoxPreferenceCheckBoxPreferenceCheckBoxPreferenceCheckBoxPreference"
                        android:summary="CheckboxPreference summary"/>
                    <Preference
                        android:title="Preference"
                        android:key="key_pre"
                        android:icon="@mipmap/ic_red_launcher"
                        android:layout="@layout/activity_main"
                        />
                    <EditTextPreference
                        android:icon="@mipmap/ic_blue_launcher"
                        android:key="key_edtkpreference"
                        android:title="EditPreference"
                        android:summary="EditPreference summary"
                        />
                </PreferenceCategory>
                </PreferenceScreen>
                 
                 

                  这里写图片描述

                  4、Preference的xml文件中的常用标签intentextra

                  在xml文件的Preference标签中,我们可以添加intent来为我们快速实现一种意图,比如说快速打开一个网页,或者快速启动一个Activity等等,还可以使用extraintent标签加参数来传递参数(再通过getIntent().getStringExtra(“key”)来获取)。

                  点击这个Preference则会自动去调用浏览器打开http://www.hao123.com网页

                      <Preference
                          android:title="Click me open the web"
                          android:key="key_pref_intent"
                          >
                          <intent android:action="android.intent.action.VIEW"
                              android:data="http://www.hao123.com"/>
                          <!--可以通过<extra>传附加信息getIntent().getStringExtra("reused_key") -->
                          <extra
                              android:name="key"
                              android:value="value"/>
                      </Preference>
                   
                   

                    启动指定类

                     <Preference
                            android:title="PREFERENCE TITLE"
                            >
                            <!-- android:targetPackage是应用程序的包名,而android:targetClass的路径在子包下的类 -->
                            <!-- android:targetPackage设置为子包,运行时则找不到Activity -->
                            <intent
                                android:action="ACTION_A_INTENT"
                                android:targetPackage="com.crazy.training"
                                android:targetClass="com.crazy.training.ui.MainActivity">
                            </intent>
                        </Preference>
                     
                     

                      三、PreferenceScreen和PreferenceCategory

                      PreferenceScreen和PreferenceCategory没有新增的属性,所有属性全部继承自Preference。其中PreferenceScreen作为顶级容器,PreferenceCategory作为次级容器(类似于SQL Group by功能暂且这么理解吧),虽然他们也是可以单独使用的,但是并不能响应onPreferenceClickonPreferenceChange事件。

                      布局和MainActivity的代码依然很简单和前面类似

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

                        这里写图片描述

                        <?xml version="1.0" encoding="utf-8"?>
                        <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
                            android:title="PreferenceScreen">
                        <PreferenceCategory
                            android:key="key_prerence"
                            android:summary="Preference Categories Summary"
                            android:title="Preference Categories">
                            <CheckBoxPreference
                                android:icon="@mipmap/ic_launcher"
                                android:key="key_chkpreference"
                                android:title="CheckBoxPreference"
                                android:summary="CheckboxPreference summary"/>
                            <EditTextPreference
                                android:icon="@mipmap/ic_blue_launcher"
                                android:key="key_edtkpreference"
                                android:title="EditPreference"
                                android:summary="EditPreference summary"
                                />
                        </PreferenceCategory>
                        </PreferenceScreen>
                         
                         

                          这里写图片描述

                          四、RingtonePreference的应用

                          RingtonePreference起作用就是供我们选择系统铃声的,除了Preference共有的属性外还新增了自己的几个独特属性。

                          新增属性说明
                          android:ringtoneType铃声类型:ringtone、notification、all、alarm
                          android:showDefault布尔值是否显示默认铃声
                          android:showSilent布尔值是否显示静音

                          应用也很简单,与Preference大同小异(注意看图)

                          <?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的管理

                            Preference的管理主要包含Preference的创建添加移除寻找特定Preference,Preference并没有直接提供相关替换的方法。

                            1、创建Preference

                            主要是通过各自对应Preference的构造方法或者直接在xml文件中定义来创建对应的Preference

                            2、addPreference添加Preference

                            添加只要是就是调用PreferenceGroup的addPreference(Preference preference)方法 来添加至容器PreferenceGroup。

                            3、findPreference寻找特定Preference

                            对于PreferenceActivityfindPreference(key)方法,我们只需要知道key值就可以找到同一xml文件下相应的Preference,勿需考虑层级和嵌套关系
                            这里写图片描述

                            4、removePreference或removeAll移除Preference

                            对于PreferenceGroupremovePreference(Preference preference)removeAll()方法,都是针对某个PreferenceGroup来处理的,所以我们必须考虑层级嵌套关系,可以分为两步:先找到PreferenceGroup和要删除的Preference,再调用PreferenceGroup的removePreference执行删除动作。

                            首先这是我们的布局

                            <?xml version="1.0" encoding="utf-8"?>
                            <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
                                android:key="key_manage_prefs">
                                <PreferenceCategory
                                    android:key="key_category"
                                    android:title="PreferenceCategory">
                                    <EditTextPreference
                                        android:key="key_edtprefs"
                                        android:title="EditTextPreference" />
                                    <PreferenceScreen
                                        android:key="key_child_prefscreen"
                                        android:title="Child PreferenceScreen">
                                        <CheckBoxPreference
                                            android:key="key_checkbox"
                                            android:title="CheckBoxPreference" />
                                    </PreferenceScreen>
                                </PreferenceCategory>
                            </PreferenceScreen>
                             
                             

                              测试主体代码

                              public class MainActivity extends PreferenceActivity {
                              
                                  private Context mContext;
                                  private Preference preference;
                                  @Override
                                  protected void onCreate(Bundle savedInstanceState) {
                                      super.onCreate(savedInstanceState);
                                      addPreferencesFromResource(R.xml.test_preference);
                              
                                      //removePreferenceByKey();
                                      mContext=getApplicationContext();
                                      preference=findPreference("key_checkbox_child");//只要是同一个xml文件下的所有Preference都能通过key直接找到
                                      preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
                                          @Override
                                          public boolean onPreferenceChange(Preference preference, Object newValue) {
                                              Toast.makeText(mContext, String.format("Preference的值为%s", newValue),Toast.LENGTH_LONG).show();
                                              return true;
                                          }
                                      });
                              
                                      preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                                          @Override
                                          public boolean onPreferenceClick(Preference preference) {
                                              Toast.makeText(mContext, "Preference Clicked",Toast.LENGTH_LONG).show();
                                              //getFragmentManager().beginTransaction().replace(android.R.id.content,new MainFragment()).commit();
                                              return false;
                                          }
                                      });
                                  }
                                      private void removePreferenceByKey(){
                                      /*PreferenceGroup preferenceGroup=(PreferenceGroup)findPreference("key_category");//先找到PreferenceGroup
                                      Preference preference=findPreference("key_edtprefs");//再找到要删除的Preference*/
                                      /*(PreferenceGroup)findPreference("key_child_prefscreen").removePreference(findPreference("key_checkbox_child"));//执行删除key为key_checkbox_child的Preference**/
                                      getPreferenceScreen().removePreference(findPreference("key_category"));//删除掉key_category及对应节点下的所有节点
                                      //ERROR//getPreferenceScreen().removePreference(findPreference("key_edtprefs"));//无效,因为getPreferenceScreen获得的是当前的顶级容器,而key_edtprefs不是它的直接字节点
                                      ((PreferenceGroup)findPreference("key_category")).removeAll();//仅删除掉key_category下对应Preference节点下的所有子节点
                                  }
                               
                               

                                这里写图片描述

                                小结

                                这篇文章主要介绍了Preference家族树中顶级成员和次级成员的应用和简单原理的说明,也基本把几乎所有相关的知识点都涉及了,Preference的基本语法都是一样的,区别在于各自不同的特性。

                                转自http://blog.csdn.net/crazymo_/article/details/51496516

                                • 0
                                  点赞
                                • 2
                                  收藏
                                  觉得还不错? 一键收藏
                                • 0
                                  评论

                                “相关推荐”对你有帮助么?

                                • 非常没帮助
                                • 没帮助
                                • 一般
                                • 有帮助
                                • 非常有帮助
                                提交
                                评论
                                添加红包

                                请填写红包祝福语或标题

                                红包个数最小为10个

                                红包金额最低5元

                                当前余额3.43前往充值 >
                                需支付:10.00
                                成就一亿技术人!
                                领取后你会自动成为博主和红包主的粉丝 规则
                                hope_wisdom
                                发出的红包
                                实付
                                使用余额支付
                                点击重新获取
                                扫码支付
                                钱包余额 0

                                抵扣说明:

                                1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
                                2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

                                余额充值