PreferenceFragment和PreferenceActivity
提要:PreferenceFragment展示中設置的值可以通過PreferenceManager.getDefaultSharedPreferences(context).來實現
【正文】
一、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:entries和android: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" ><!-- 設置的類別 --><PreferenceCategoryandroid:key="mylocation"android:summary="我的位置"android:title="我的位置源" ><CheckBoxPreferenceandroid:key="wireless_network"android:summary="使用無線網絡查看應用程序(例如Google地圖)中的位置"android:title="使用無線網絡" /><CheckBoxPreferenceandroid:key="gps_satellite_setting"android:summary="定位時,精確到街道級別(取消選擇可節約電量)"android:title="啟用GPS衛星設置" /></PreferenceCategory><PreferenceCategoryandroid:key="mymessage"android:summary="個人信息設置"android:title="個人信息設置" ><CheckBoxPreferenceandroid:key="yesno_save_individual_info"android:title="是否保存個人信息" /><EditTextPreferenceandroid:key="individual_name"android:summary="請輸入真實姓名"android:title="姓名 " /><ListPreferenceandroid: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的狀態保持一致。
運行效果如下:
這樣,我們的功能就實現了。
總結
以上是生活随笔為你收集整理的PreferenceFragment和PreferenceActivity的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: eclipse adt 插件离线安装
- 下一篇: 前端学习(2851):简单秒杀系统学习之