如果你想在app 中加入Setting 的功能讓使用者可以修改app 的功能和行為, 甚至將Setting value同步到 System Setting , Preference APIs 是一個不錯的選擇, 它的UI呈現方式就像 ListView 一樣, 而每個在ListView 中的subView 都可以宣告一個Key 為的是可以在SharedPreference 中存取資料, 如此一來Preference API 就會自動的幫我們儲存每個subView資料的變化, 讓我們省了不少功夫。
首先第一步要做的就是定義 XML, 將Setting 中會出現的各種Preference object 使用階層式的方式在XML 中定義清楚, 我們在 res/xml 中產生一個 XML 檔案preference.xml 如下:
在XML 檔案中 root element 必定為 PreferenceScreen, 代表著一個全新的Setting 畫面並且在其中加入我們所需要的Preference objects, 通常我們只會用到一個XML 檔案, 因為如果有需要新的Setting 畫面需求, 可以在root PreferenceScreen 中加入另一個PreferenceScreen 形成巢狀Setting。
我們使用Eclipse editor 的 Structure mode來編輯preference.xml, 這樣對於preference.xml 階層式的架構就非常清楚了, 所有的 Preference objects 都在root Preference中, 另外還加入了一個Second PreferenceScreen, 當使用者點選時會跳出一個新的Setting 畫面, 無需create 一個額外activity。
接下來介紹幾個常用的 attribute:
android:key
最重要的屬性, 必須是一個唯一的Key供SharedPreference 儲存setting value使用, 之後在PreferenceActivity 中我們也是靠Key 來識別不同的Preference object。
android:title
Preference object 出現在Setting 畫面中的名稱。
android:defaultValue
SharedPreference 中儲存的初始值
android:summary
Preference object 出現在Setting 畫面中的說明文字, 以較小的字出現在title 下方。
接下來先附上完整的 preference.xml, 再來針對每個Preference object 作介紹
EditTextPreference : 當使用者選擇時會跳出Dialog, 而關於這個Dialog 的屬性可以使用 Editor 事先編輯, 特別的是EditText 能宣告的屬性, EditTextPreference 也能拿來使用, 所以在這邊宣告了 inputType 屬性為只能輸入Decimal number, 另外我們將使用者輸入的數字顯示在summay 中, 不過這邊需要在PreferenceActivity 中加入此功能, 這部分稍後會提到。
ListPreference : 顯示一組有著Radio button 的List, 要使List 能呈現內容的話, 要事先為List import Entry array和Entry value array, 我們可以在 /res/value 中宣告 string array 再使用Editor 引入即可, array 內容如下:
PreferenceActivity
Hello world!
Settings
MainActivity
- First item
- Second item
- Third item
- 0
- 1
- 2
Entry 宣告了要顯示在List 中的內容, Entry value 對應為每個 Entry 內容所代表的value
另外值得一提的是因為選擇ListPrefence時會跳出Dialog 所以如果在Editor 中再宣告Dialog Message 屬性時就會導致顯示內容錯誤, 另外Dialog 只會出現Negative Button !
RingtonePreference : 讓使用者選擇手機上的鈴聲, 將被選擇鈴聲的URI 以string 格式儲存在SharedPreference 中, showSilent 屬性表示列表中是否包含靜音的選項, ringtoneType 用來限制列表中顯示的鈴聲類型。
PreferenceCategory : 單純的將Prefence object 分類而已, 在針對不同的Category 內加入Preference object, 可以看到畫面上的"第一個分類", "第二個分類"....均是。
Preference : 更單純, 通常只是被用來當作"說明"功能而已。
稍微簡介了用到的Preference Objects 之後, 開始來看PreferenceActivity.java 程式主要在處理每個Preference object 初始的Summary 設定, 和註冊value change 的事件。
package com.example.preferenceactivity;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceScreen;
import android.preference.RingtonePreference;
import android.view.Menu;
public class MainActivity extends PreferenceActivity implements OnPreferenceChangeListener
{
EditTextPreference editTextPreference, secondEditTextPreference;
ListPreference listPreference;
RingtonePreference ringtonePreference;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference); // 記得替換掉預設的 setContentView(R.layout.activity_main)
editTextPreference = (EditTextPreference) findPreference("EditTextP");
editTextPreference.setOnPreferenceChangeListener(this);
//替Preference註冊value改變事件, 因為我們要動態的更新Summary content
editTextPreference.setSummary("EditTextPreference Value:" +editTextPreference.getText());
listPreference = (ListPreference) findPreference("ListP");
listPreference.setOnPreferenceChangeListener(this);
listPreference.setSummary("ListPreference Value:"+ listPreference.getEntry());
ringtonePreference = (RingtonePreference) findPreference("RingtoneP");
ringtonePreference.setOnPreferenceChangeListener(this);
//---In the second Screen
secondEditTextPreference = (EditTextPreference) findPreference("SPCEditTextP");
secondEditTextPreference.setOnPreferenceChangeListener(this);
secondEditTextPreference.setSummary("EditTextPreference Value:" +secondEditTextPreference.getText());
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
Preference preference)
{
// TODO Auto-generated method stub
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
public boolean onPreferenceChange(Preference preference, Object newValue)
{
// TODO Auto-generated method stub
if(preference.getKey().equals("EditTextP")) //根據不同的key來辨別不同的Preference
preference.setSummary("EditTextPreference Value:" +newValue);
else if(preference.getKey().equals("ListP"))
preference.setSummary("ListPreference Value:" +((ListPreference) preference).getEntries()[Integer.parseInt(newValue.toString())]);
//從Entry中對應顯示使用者選擇的item value
else if(preference.getKey().equals("RingtoneP"))
preference.setSummary("RingtonePreference Value:" +newValue);
else if(preference.getKey().equals("SPCEditTextP"))
preference.setSummary("EditTextPreference Value:" +newValue);
return true;
}
}
最後當我們成功儲存了每個Preference objects value 後, 該透過甚麼方法取得呢?
網路上建議的作法:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return value preferences 為 context 所使用的preference file, 接下來就可以對 preferences 進行數值的存取了。
相關文章: