在Ap中有時需要設置一些配置參數,這些參數通過配置文件保存。
爲了設置這些參數,需要提供一個UI,針對這種需求,Android提供了preferenceActivity。
PreferenceActivity通過讀取預先定義的xml文件來生成界面,並能夠自動的根據用戶的操作來修改參數,並保存到配置文件中供讀取。
1.MainActivity:
按下Menu按鍵彈出菜單,點擊菜單啓動SettingActivity。
2.SettingActivity繼承自PreferenceActivity:
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.settings);
- }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.settings); }
在onCreate函數中加載參數定義文件。
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
當參數值被改變時會調用此Listener,可以在此Listener中作一些界面刷新工作,比如當前參數值改變爲新的值。
- Preference android.preference.PreferenceActivity.findPreference(CharSequence key);
Preference android.preference.PreferenceActivity.findPreference(CharSequence key);
獲取指定key所對應的preference對象,即使此key在配置文件中尚未保存,也能夠得到preference對象,而不會是null。
3.settings.xml:保存在xml目中的參數定義文件,在創建Android XML文件時選擇Preference即可創建一個空的參數定義文件。
- <?xml version="1.0" encoding="utf-8"?>
- <PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android">
- </PreferenceScreen>
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> </PreferenceScreen>
添加一個CheckBoxPreference子項,並設置屬性:
Key:checkbox_key
Title:CheckBox Item
Summary:test check box item
- <?xml version="1.0" encoding="utf-8"?>
- <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
- <CheckBoxPreference android:key="checkbox_key"
- android:title="CheckBox Item" android:summary="test check box item"></CheckBoxPreference>
- </PreferenceScreen>
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <CheckBoxPreference android:key="checkbox_key" android:title="CheckBox Item" android:summary="test check box item"></CheckBoxPreference> </PreferenceScreen>
key是用來訪問此參數的值的關鍵字,保存後的配置文件類似如下內容:
- <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
- <map>
- <boolean name="checkbox_key" value="true" />
- </map>
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <map> <boolean name="checkbox_key" value="true" /> </map>
啓動Ap,點擊菜單,即可看到參數設置界面,並且當用戶點擊操作改變了參數值後,也會被自動保存。
4.使用參數值:
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
boolean check_test = sp.getBoolean("checkbox_key", false);
進階:
1.保存參數文件的路徑:
/data/data/包名/shared_prefs/包名_preferences.xml
如果想指定保存文件名,可使用:
getPreferenceManager().setSharedPreferencesName("配置文件名");
2.其他的參數配置項:
2.1 EditTextPreference:
- <EditTextPreference android:dialogTitle="Edit Text Dialog"
- android:key="edittext_key" android:dialogMessage="Please Input text"
- android:title="EditText Item" android:summary="test edittext item"></EditTextPreference>
<EditTextPreference android:dialogTitle="Edit Text Dialog" android:key="edittext_key" android:dialogMessage="Please Input text" android:title="EditText Item" android:summary="test edittext item"></EditTextPreference>
此參數設置項會彈出一個文本輸入對話框,並在配置文件中生成類似以下內容:
<string name="edittext_key">this is a good text</string>
彈出對話框的圖標、標題、提示信息、Icon、以及兩個按鈕的文本都可以設定。
至於自定義對話框的佈局,雖然有這個屬性,但是自定義佈局後就不能自動保存值了,
本來以爲只要放一個ID和原來一樣的EditText就能,但是查看源代碼,發現其EditText是new出來的,沒法替代。
2.2 PreferenceCategory:一個分類分隔條。只有title屬性有效。
2.3 PreferenceScreen:此項包含的所有子項在新屏幕上顯示,就好像進入二級菜單。
2.4 ListPreference:會彈出一個列表對話框供選擇。
2.5 RingtonePreference:會彈出系統鈴聲列表供選擇。
2.6 Preference:通用參數項。點擊後需要程序自己響應事件。
3.自定義選項:
系統的提供的界面有時不能滿足需要,這時就需要自定義選項了。
有兩種方法可以實現自定義選項,一是用Preference作爲選項,並重新實現onPreferenceTreeClick函數。
一是自定義一個類,類似於EditTextPreference這種系統內置的類,然後引用。
3.1使用一個Preference佔位,然後重新實現onPreferenceTreeClick()函數:
- public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
- String key = preference.getKey();
- if( key != null ){
- if(key.equals("some_key")) {
- showDialog(DIALOG_SOME_KEY);
- }
- }
- return super.onPreferenceTreeClick(preferenceScreen, preference);
- }
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { String key = preference.getKey(); if( key != null ){ if(key.equals("some_key")) { showDialog(DIALOG_SOME_KEY); } } return super.onPreferenceTreeClick(preferenceScreen, preference); }
當點擊指定key的Preference時,就會彈出對話框,然後在合適的時機使用如下代碼保存參數即可。
- SharedPreferences.Editor editor = preference.getEditor();
- editor.putLong("ttt", 123);
- editor.commit();
SharedPreferences.Editor editor = preference.getEditor(); editor.putLong("ttt", 123); editor.commit();
此種方法如果要觸發onSharedPreferenceChanged(),可以通過preference.getOnPreferenceChangeListener()獲取listener然後來呼叫。
3.2自定義選項類:
此處以一個選擇時間的對話框選項爲例。
3.2.1 從DialogPreference繼承一個類:
- public class TimePreference extends DialogPreference
public class TimePreference extends DialogPreference
3.2.2 構造函數:
- public TimePreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- setDialogLayoutResource(R.layout.time_preference); //加載佈局文件
- }
public TimePreference(Context context, AttributeSet attrs) { super(context, attrs); setDialogLayoutResource(R.layout.time_preference); //加載佈局文件 }
3.3.3 佈局文件:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <TimePicker android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="@+id/timePicker_preference" android:layout_centerHorizontal="true"></TimePicker>
- </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TimePicker android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="@+id/timePicker_preference" android:layout_centerHorizontal="true"></TimePicker> </RelativeLayout>
定義了一個id爲timePicker_preference的TimePicker。
3.3.4 界面初始化:在dialog的函數中通過id找到TimePicker,然後使用已經存儲的值或者默認值,再設置到TimerPicker中。
- @Override
- protected void onBindDialogView(View view) {
- super.onBindDialogView(view);
- mPicker = (TimePicker)view.findViewById(R.id.timePicker_preference);
- if(mPicker != null) {
- mPicker.setIs24HourView(true);
- long value = mValue;
- Date d = new Date(value);
- mPicker.setCurrentHour(d.getHours());
- mPicker.setCurrentMinute(d.getMinutes());
- }
- }
@Override protected void onBindDialogView(View view) { super.onBindDialogView(view); mPicker = (TimePicker)view.findViewById(R.id.timePicker_preference); if(mPicker != null) { mPicker.setIs24HourView(true); long value = mValue; Date d = new Date(value); mPicker.setCurrentHour(d.getHours()); mPicker.setCurrentMinute(d.getMinutes()); } }
3.3.5 保存值:在對話框關閉時保存值。
- @Override
- protected void onDialogClosed(boolean positiveResult) {
- super.onDialogClosed(positiveResult);
- if(positiveResult) {
- Date d = new Date(0, 0, 0, mPicker.getCurrentHour(), mPicker.getCurrentMinute(), 0);
- long value = d.getTime();
- if(callChangeListener(value)) {
- setValue(value);
- }
- }
- }
@Override protected void onDialogClosed(boolean positiveResult) { super.onDialogClosed(positiveResult); if(positiveResult) { Date d = new Date(0, 0, 0, mPicker.getCurrentHour(), mPicker.getCurrentMinute(), 0); long value = d.getTime(); if(callChangeListener(value)) { setValue(value); } } }
3.3.6 使用此preference:
在參數定義文件中增加:
- <cn.demo.pa.TimePreference android:key="time_test" android:title="Test time preference"/>
<cn.demo.pa.TimePreference android:key="time_test" android:title="Test time preference"/>
類似於使用自定義控件。
運行即可看到效果:
3.3.7 使用默認值:
在參數定義文件中增加一個定義:
- <cn.demo.pa.TimePreference android:key="time_test" android:title="Test time preference" android:defaultValue="1000000"/>
<cn.demo.pa.TimePreference android:key="time_test" android:title="Test time preference" android:defaultValue="1000000"/>
並且自定的preference類中要實現兩個函數:
- @Override
- protected Object onGetDefaultValue(TypedArray a, int index) {
- return a.getString(index);
- }
@Override protected Object onGetDefaultValue(TypedArray a, int index) { return a.getString(index); }
以及
- @Override
- protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
- long value;
- if(restorePersistedValue) value = getPersistedLong(0);
- else {
- value = Long.parseLong(defaultValue.toString());
- }
- setValue(value);
- }
@Override protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { long value; if(restorePersistedValue) value = getPersistedLong(0); else { value = Long.parseLong(defaultValue.toString()); } setValue(value); }
當PreferenceActivity啓動時會構造TimePreference,此時會調用onGetDefaultValue,然後調用 onSetInitialValue,在onSetInitialValue保存初始值,並在onBindDialogView中使用保存的值從而可以使 用默認值。
http://blog.163.com/guozioo@126/blog/static/6408694720106711453584/