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的狀態保持一致。

運行效果如下:

這樣,我們的功能就實現了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM