• Android数据存储(二)----PreferenceFragment详解


    【声明】 

    欢迎转载,但请保留文章原始出处→_→ 

    生命壹号:http://www.cnblogs.com/smyhvae/

    文章来源:http://www.cnblogs.com/smyhvae/p/4020469.html

     

    【正文】

    一、PreferenceFragment的引入:

    PreferenceActivity是一个非常有用的基类,当我们开发Android项目时避免不了选项设置,这些设置习惯用Preference来保存。Android专门为这种Activity提供了便捷的基类PreferenceActivity。如果继承自Preference则不需要自己控制Preference的读写,PreferenceActivity会为我们处理一切。

    PreferenceActivity与普通的Activity不同,它不是使用界面布局文件,而是使用选项设置的布局文件

    选项设置布局文件以PreferenceScreen作为根元素来表示定义一个参数设置界面布局。

    从Android 3.0以后官方不再推荐直接让PreferenceActivity加载选项设置布局文件,而是建议使用PreferenceFragment,二者用法类似。所以今天就来学习一下。

    下面的这张截图就是一个典型的例子:

    我们会看到整个页面被分为几组:无线和网络、个人、账户、设备、系统。这个分组(或者叫分类)就是PreferenceCategory

    Wifi右边有开关,这一项就是CheckBoxPreference;其他还有ListPreference和EditTextPreference。

    你的每一次设置,都会被Preference自动保存下来,这就是setting的数据持久化。每个Preference都是以键值对的形式保存下来的

    PreferenceActivity的继承关系图:(不推荐使用)

    PreferenceFragment的继承关系图:(推荐使用

    二、在XML文件中Preference的种类:

    根节点中一定是<PreferenceScreen> 元素,在这个元素中可以添加不同的Preference。常见的Preference控件有:

    • 直接子类:DialogPreference, PreferenceGroup, RingtonePreference, TwoStatePreference
    • 非直接子类:CheckBoxPreference, EditTextPreference, ListPreference, MultiSelectListPreference, PreferenceCategory, PreferenceScreen, SwitchPreference

    我们还是通过实际的例子来实现吧。 

    【实例】

    先新建一个工程文件:

    新建类PrefFragment.java,让其继承PreferenceFragment,并加载选项设置的布局文件:(核心代码是第6行和13行)

     1 package com.example.m05_preffragment01;
     2 
     3 import android.os.Bundle;
     4 import android.preference.PreferenceFragment;
     5 
     6 public class PrefFragment extends PreferenceFragment {
     7     @Override
     8     public void onCreate(Bundle savedInstanceState) {
     9         // TODO Auto-generated method stub
    10         super.onCreate(savedInstanceState);
    11         
    12         //从xml文件加载选项 
    13         addPreferencesFromResource(R.xml.preferences);
    14     }
    15 }

    然后,在MainActivity.java中加载上面的Fragment:

     1 package com.example.m05_preffragment01;
     2 
     3 import android.app.Activity;
     4 import android.app.FragmentManager;
     5 import android.app.FragmentTransaction;
     6 import android.os.Bundle;
     7 
     8 public class MainActivity extends Activity {
     9 
    10     @Override
    11     protected void onCreate(Bundle savedInstanceState) {
    12         super.onCreate(savedInstanceState);
    13         setContentView(R.layout.activity_main);
    14         
    15         //加载PrefFragment
    16         FragmentManager fragmentManager = getFragmentManager();
    17         FragmentTransaction transaction = fragmentManager.beginTransaction();
    18         PrefFragment prefFragment = new PrefFragment();
    19         transaction.add(R.id.prefFragment, prefFragment);
    20         transaction.commit();
    21         
    22     }
    23     
    24 }

    接下来的知识就是重头戏了,既然PrefFragment要加载选项设置的布局文件R.xml.preferences,那我们就来定义一下这个preferences.xml

    在res目录下新建立一个xml目录,在该目录中新建文件preferences.xml:

    关于preferences.xml的文件里面的代码,请看下面这一段。

    五、preference详解:

    1、<PreferenceCategory>的方式进行分组

    preferences.xml举例如下:

    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
        
        <!-- 设置的类别 -->
        <PreferenceCategory 
            android:key="mylocation"
            android:summary="我的位置"
            android:title="我的位置源">              
            <CheckBoxPreference 
                android:key="wireless_network"
                android:summary="使用无线网络查看应用程序中的位置"
                android:title="使用无线网络"/>          
        </PreferenceCategory>
        
        <PreferenceCategory 
            android:key="mymsg"
            android:summary="个人信息"
            android:title="个人信息">              
            <EditTextPreference 
                android:key="myname"
                android:title="请输入真实姓名"
                android:summary="姓名"/>          
        </PreferenceCategory>    
        
    </PreferenceScreen>

    上方代码中,一个<PreferenceCategory>就是一个类别,单个的<PreferenceCategory>可以放入任意的Preference控件。我们在第一个类别中放入了CheckBoxPreference控件,在第二个类别中放入了EditTextPreference控件。运行效果如下:

    运行时候,会自动在/data/data/<packagename>/shared_prefs/目录生成一个文本文件:

    注:这个文本的文件名太长了,我们可以在上方PrefFragment.java的第13行代码后面加上这样一句话来修改文件名:(这里我将文件名修改为:mysetting)

    getPreferenceManager().setSharedPreferencesName("mysetting");

    文本内容如下:

    我们现在在CheckBoxPreference中打钩,然后在EditTextPreference中输入内容:

    文本内容显示如下:

    2、显示子屏幕subscreens方式的进行分组:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:title="Settings" >
     4 
     5     <PreferenceScreen
     6         xmlns:android="http://schemas.android.com/apk/res/android"
     7         android:summary="settings about emotions"
     8         android:title="Emotions" >
     9         <CheckBoxPreference
    10             android:defaultValue="true"
    11             android:summaryOff="No,I am sorry."
    12             android:summaryOn="Yes,I love you!"
    13             android:title="Love me?" >
    14         </CheckBoxPreference>
    15         <CheckBoxPreference
    16             android:defaultValue="false"
    17             android:summaryOff="No,you are a good person."
    18             android:summaryOn="Yes,I hate you!"
    19             android:title="Hate me?" >
    20         </CheckBoxPreference>
    21     </PreferenceScreen>
    22     
    23     <PreferenceScreen
    24         xmlns:android="http://schemas.android.com/apk/res/android"
    25         android:summary="settings about relations"
    26         android:title="Relations" >
    27         <CheckBoxPreference
    28             android:defaultValue="true"
    29             android:summaryOff="No,I am sorry."
    30             android:summaryOn="Yes,we are family!"
    31             android:title="Family?" >
    32         </CheckBoxPreference>
    33         <CheckBoxPreference
    34             android:defaultValue="false"
    35             android:summaryOff="No,I am sorry."
    36             android:summaryOn="Yes,we are friends!"
    37             android:title="Friends?" >
    38         </CheckBoxPreference>
    39     </PreferenceScreen>
    40 
    41 </PreferenceScreen>

    运行效果如下:

    点击上方第一个preference,进入下图中左侧界面;点击上方第二个preference,进入下图中右侧界面。效果如下:

    3、ListPreference控件:

    点击该控件后,将列出一个单选按钮的列表。用法如下:

    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
        
        <PreferenceCategory 
            android:key="mylocation"
            android:summary="我的位置"
            android:title="我的位置源">    
            <ListPreference 
                android:key="mycities"
                android:title="所属城市"
                android:summary="点击弹出城市列表"
                android:dialogTitle="请选择城市"
                android:entries="@array/cities"
                android:entryValues="@array/cities"/>
        </PreferenceCategory>
        
    </PreferenceScreen>

    上方代码中,PreferenceScreen为根标签,ListPreference为子标签。ListPreference的常见属性如下:

    • android:key 唯一标识符,和android:id相类似,PreferenceManager可以以其为参数通过findPreference获取指定的preference 。 注意,这个android:key的值也是Preference文件里面的XML“键”名
    • android:title 大标题
    • android:summary 标题下面的小字(这个要作为选项卡才有)
    • android:entries 弹出的对话框中,列表显示的文本内容,注意哦,这里指定的是一个数组。
    • android:entryValues 与android:entries相对应的值
    • android:defaultValue 当对应值不存在时的默认值
    • android:dialogTitle 弹出的对话框中的标题信息

    关于android:entriesandroid:entryValues的区别,要强调一下:

    • android:entries:The human-readable array to present as a list. 是展现给用户的列表的值。
    • android:entryValues :he array to find the value to save for a preference when an entry from entries is selected. 展现的用户的选择列表的每个元素选择后,需要存储到手机中,这里的entryValues就是列表中各个元素被选择后存储到手机中的值(通过sharedPreferences保存在/data/data/<packagename>/shared_prefs/目录下)。简单的说就是此处是数据库中的值。上面的android:entries是展现给用户的列表的值。

    我们在上方代码中的第13、14行引用了数据,紧接着我们要在values目录下的strings.xml文件中定义这个被引用的城市列表(即数据来源):

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <resources>
     3 
     4     <string name="app_name">m05_PrefFragment01</string>
     5     <string name="action_settings">Settings</string>
     6     <string name="hello_world">Hello world!</string>
     7 
     8     <string-array name="cities">
     9         <item>成都</item>
    10         <item>重庆</item>
    11         <item>黄冈</item>
    12     </string-array>
    13 
    14 </resources>

    上方代码中,8至12行:即加粗部分,是我添加的数据源。

    运行程序效果如下:

    六、监听事件onPreferenceTreeClick()方法:

    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen Preference preference) 

    当任何一个preference控件被点击,都将触发该方法。但是可以通过preference.getKey()这个方法找到具体是哪个preference被点击了,因为每个preference的key都是唯一的

    【实例】

    现将preferences.xml这个设置选项的布局文件,定义如下:

    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <!-- 设置的类别 -->
        <PreferenceCategory
            android:key="mylocation"
            android:summary="我的位置"
            android:title="我的位置源" >
            <CheckBoxPreference
                android:key="wireless_network"
                android:summary="使用无线网络查看应用程序(例如Google地图)中的位置"
                android:title="使用无线网络" />
            <CheckBoxPreference
                android:key="gps_satellite_setting"
                android:summary="定位时,精确到街道级别(取消选择可节约电量)"
                android:title="启用GPS卫星设置" />
        </PreferenceCategory>
        
        <PreferenceCategory
            android:key="mymessage"
            android:summary="个人信息设置"
            android:title="个人信息设置" >
            <CheckBoxPreference
                android:key="yesno_save_individual_info"
                android:title="是否保存个人信息" />
            <EditTextPreference
                android:key="individual_name"
                android:summary="请输入真实姓名"
                android:title="姓名 " />
            <ListPreference
                android:entries="@array/cities"
                android:entryValues="@array/cities"
                android:key="mycity"
                android:summary="所属城市"
                android:title="所属城市" />
        </PreferenceCategory>
    
    </PreferenceScreen>

    运行效果如下:

    现在我们需要做的是,选中上方红框中的CheckBoxPreference,对应下面的EditTextPreference为编辑状态;否则,如果CheckBoxPreference没有被选中,则EditTextPreference为不可编辑状态。修改PrefFragment.java的代码,其完整版代码如下:

     1 package com.example.m05_preffragment01;
     2 
     3 import android.os.Bundle;
     4 import android.preference.CheckBoxPreference;
     5 import android.preference.EditTextPreference;
     6 import android.preference.Preference;
     7 import android.preference.PreferenceFragment;
     8 import android.preference.PreferenceScreen;
     9 
    10 public class PrefFragment extends PreferenceFragment {
    11 
    12     @Override
    13     public void onCreate(Bundle savedInstanceState) {
    14         // TODO Auto-generated method stub
    15         super.onCreate(savedInstanceState);
    16         
    17         //从xml文件加载选项 
    18         addPreferencesFromResource(R.xml.preferences);
    19     }
    20     
    21     @Override
    22     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
    23             Preference preference) {
    24         //如果“保存个人信息”这个按钮被选中,将进行括号里面的操作
    25         if("yesno_save_individual_info".equals(preference.getKey())) {            
    26             CheckBoxPreference checkBoxPreference = (CheckBoxPreference)findPreference("yesno_save_individual_info");
    27             EditTextPreference editTextPreference = (EditTextPreference)findPreference("individual_name");
    28             //让editTextPreference和checkBoxPreference的状态保持一致
    29             editTextPreference.setEnabled(checkBoxPreference.isChecked());
    30         }
    31         // TODO Auto-generated method stub
    32         return super.onPreferenceTreeClick(preferenceScreen, preference);
    33     }
    34 }

    代码解释:

    当任何一个preference控件被点击,都将触发onPreferenceTreeClick()方法(22行),但是可以通过preference.getKey()这个方法找到具体是哪个preference被点击(25行)。

    26行、27行:通过public Preference findPreference(CharSequence key)找到对应的preference,然后强转为它的子类。

    29行:核心代码,让editTextPreference和checkBoxPreference的状态保持一致。

    运行效果如下:

    这样,我们的功能就实现了。

  • 相关阅读:
    HAL 分析
    Ubuntu 11.04 安装后要做的20件事情
    IOStableViewCell自适应高度cell里面放的是UIlable
    IOS支持的字体
    IOS TableView学习资源
    产品与市场
    软件质量与公司盈利
    计算机流派
    让你的软件支持繁体中文
    系统规划设置心得
  • 原文地址:https://www.cnblogs.com/qianguyihao/p/4020469.html
Copyright © 2020-2023  润新知