Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Settings(Preferences)開發

Android Settings(Preferences)開發

編輯:關於Android編程

在Android的app開發中,很多時候我們的app需要提供用戶一個用戶體驗統一的,友好的setting界面,也就是設置界面。在android系統中,就有一個settings設置的系統應用,專門用戶設置系統的一些用戶屬性。那麼這樣的setting界面我們怎麼開發呢?android為我們提供了一個程序員非常友好的preferences開發包:android.preference。這個開發包中,包含了眾多我們在開發app的設置界面時需要的類,這個包的詳情頁:
https://developer.android.com/reference/android/preference/package-summary.html
下面我們結合google的開發指導文檔,講解一下android中的preferences設置界面的開發。Google的開發知道文檔:
https://developer.android.com/guide/topics/ui/settings.html
另外,在開發setting界面的時候,這個界面的設計也是有一定的設置哲學的,在進行自定義開發的時候最好遵循這些設置哲學,不至於使你的app界面顯得太過於突兀。Google關於Setting界面設置的建議文檔:
https://material.google.com/patterns/settings.html
如果你想打造更好HMI的app以及線上web站點的話,那麼你最好遵循這些設計原則。
我的demo代碼地址:
https://github.com/CreateChance/AndroidSettingsDemo

為什麼使用preferences來開發?

這是一個好問題,人們在做一些事情之前總是喜歡問下為什麼。在通常app的開發過程中,我們都會為我們的app提供一個設置界面,易方便用戶對我們的應用做一些必要的個性化的設置。但是很多時候,我們需要提供的設置項很多,關系也有些復雜,如果自己通過布局文件的形式去做的話,會比較麻煩,會使得UI布局的層級不夠清晰,不容易日後維護和升級。因此,Google為了減輕廣大開發者在開發setting界面時的困苦,google推出了preferences包。preferences包,顧名思義,就是使用android中的sharedpreferences技術來將我們的設置數據進行本地持久化,並且提供了內部封裝的自動數據同步邏輯,使得我們的開發者只關心自己的app需要有那些設置,這些設置項的位置在哪裡等業務邏輯,並不用關系數據怎麼存儲,數據怎麼同步的非業務邏輯,這樣一來,就大大減少了。但是由於這裡使用的是sharedpreferences技術,也就是xml技術來存儲數據的,因此如果你的數據結構和邏輯比較復雜的話那麼你最好使用sqlite數據庫來存儲。這裡我們總結一下preferences包的好處:
1. 簡化setting界面開發,使得界面和邏輯解耦
2. 簡化需要保存的數據結構和邏輯比較簡單的情況下的輕量級存儲的開發

開發的步驟

使用preferences包來開發基本不需要開發者了解sharedpreferences持久化技術,但是如果你了解的話,可以幫助你更好地理解preferences setting的開發。
在開始之前,我們先看下android.preference包中有哪些類:

這裡寫圖片描述

這些類中,PreferenceActivity和PreferenceFragment是我們界面開發重點關注的類,他們是構建設置界面的基礎。這裡需要說明一下,從android 3.0(api 11)之後,google一直建議開發使用fragment開發不要使用activity開發,因為fragment的開發使得界面編程更加靈活,代碼更加清晰易懂。因此在設置界面開發過程中,google也是推薦使用PreferenceActivity內嵌PreferenceFragment方式進行開發。其中PreferenceActivity只是負責設置選項的設置,具體的設置界面和邏輯需要使用PreferenceFragment完成。

android提供的設置界面組件

android提供了很多用於構建設置界面的ui組件,這些組件就在上面給出的包圖中,那些以常用view組件名開頭的preference就是android提供的設置界面組件。下面3個是最常用的組件:
1. CheckBoxPreference
這是一個提供check box的設置界面組件,使得用戶可以通過勾選的方式進行設置。
2. ListPreference
這個組件當用戶單擊的時候會彈出一個對話框讓用戶以單選的形式進行選擇。
3. EditTextPreference
這個組件當用戶單擊的時候會彈出一個對話框,對話框上有一個edit text組件,讓用戶輸入。
下面我給出的demo中就會演示這3個組件的使用,其他的組件使用方式大同小異。

開發第一步:定義PreferenceActivity的header布局xml

前面我們說道,PreferenceActivity在3.0+系統上,只是負責設置界面的顯示,不負責具體設置項的問題。因此,為了讓PreferenceActivity顯示我們的設置項,我們需要定義header文件,這個文件存放在res的xml目錄下:
preference_headers.xml


 

這裡我放了兩個設置:設置1和設置2,並且每個設置下面都有一個summary描述。同時需要說明的是,上面的文件只是定義了兩個選項,但是這兩個選項中的內容是需要通過fragment來實現的,因此這裡我指定了實際處理的fragment類。
定義完header文件後我們就可以在PreferenceActivity的子類中復寫onBuildHeaders和isValidFragment這兩個方法。onBuildHeaders方法是用來加載並且顯示上面我們定義的header文件的,isValidFragment這個方法即使告訴是系統目前的這個fragment是不是一個有效的fragment,這兩個方法都是強制必須實現的。下面是我的代碼:

public class MainActivity extends PreferenceActivity {

    @Override
    public void onBuildHeaders(List
target) { super.onBuildHeaders(target); loadHeadersFromResource(R.xml.preference_headers, target); } @Override protected boolean isValidFragment(String fragmentName) { Log.d("DEBUG", "isValidFragment, fragmentName: " + fragmentName); return true; } }

可以看到,MainActivity根本都不用復寫onCreate方法和調用setContentView方法設置布局。
運行之後可以看到這樣的界面:
這裡寫圖片描述

開發第二步:定義preference布局xml

上面的header只是定義了設置項,但是設置項中有什麼我們還沒有定義。現在我們就要定義這個布局文件,上面的header文件指定了處理的fragment,因此當用戶點擊上面的設置項的時候,就會實例化相應的fragment並且添加到當前的activity中顯示。
preference布局文件必須以PreferenceScreen為根,其中的元素可以是上面我們提到的3個常見組件,並且preference提供了布局分組功能,也就是說可以讓我們把幾個設置歸為一個類別進行分類顯示,這個使用PreferenceCategory描述,下面是我的布局文件:



    

    

        

        

        

    

    

        

        

        

    

    


我定義了一個鈴聲設置,兩個demo分組設置,還有一個高級設置的switch按鈕設置。高級設置也是一個preference的xml文件定義如下:



    
        
    

最後需要說明一下,前面我們定義了一個列表設置項,因此我們需要array來提供列表顯示項和相應的值,我們可以把它定義在array資源文件中:
arrays.xml



    
        item 1
        item 2
        item 3
        item 4
        item 5
    

    
        value 1
        value 2
        value 3
        value 4
        value 4
    


定義完畢preference文件之後,我們還需要定義PreferenceFragment的子類來顯示這個布局文件。

開發第三步:定義PreferenceFragment的子類

我們只要新建一個類並且繼承自PreferenceFragment類就可以,然後我們還需要復寫它的onCreate方法,在這個方法中調用addPreferencesFromResource方法顯示我們上面的布局文件。同時我們還需要監聽高級設置的switch button的按下的值來決定是不是需要顯示高級設置界面,因此需要在這個fragment啟動的時候判斷高級設置項的狀態,如果發現高級設置被關閉了,那麼就要隱藏高級設置,反之則要顯示。
這裡有幾個問題需要處理:
1. 怎麼監聽高級設置的按下情況?
答:實現sharedpreference的OnSharedPreferenceChangeListener接口來實現數據監聽,因為preference設置時使用sharedpreference存儲的。
2. 怎麼隱藏或者顯示高級設置?
我們在啟動fragment的時候調用addPreferencesFromResource顯示我們定義的布局文件,這個方法是將參數中指定的resource文件添加到當前顯示ui結構中,因此我們可以通過這個方法顯示高級設置界面。那麼怎麼隱藏呢?我們通過addPreferencesFromResource添加了界面之後,fragment中就會有一個根preference,我們通過的這個根的removePreference方法來移除我們的高級設置界面,removePreference方法的參數是一個preference對象,這個可以通過PreferenceFragment的findPreference(String key)方法來獲得目前已經添加到該fragment中顯示的preference。這樣我們就可以控制高級界面的顯示和隱藏了。PreferenceFragment子類代碼如下:

public class PrefsFragmentOne extends PreferenceFragment
        implements SharedPreferences.OnSharedPreferenceChangeListener{

    private PreferenceScreen screen = null;

    public PrefsFragmentOne() {
        // Required empty public constructor
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        addPreferencesFromResource(R.xml.preference_settings);

        screen = getPreferenceScreen();
    }

    @Override
    public void onResume() {
        super.onResume();
        getPreferenceScreen().getSharedPreferences()
                .registerOnSharedPreferenceChangeListener(this);

        SwitchPreference switchPreference = (SwitchPreference) findPreference("show_advanced_setting");
        if (switchPreference.isChecked()) {
            addPreferencesFromResource(R.xml.preference_advanced_setting);
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        getPreferenceScreen().getSharedPreferences()
                .unregisterOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        getActivity().setTitle("設置1");
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        Log.d("DEBUG", "key: " + key);
        if ("show_advanced_setting".equals(key)) {
            boolean enabled = sharedPreferences.getBoolean(key, false);

            if (enabled) {
                // show advanced setting here.
                addPreferencesFromResource(R.xml.preference_advanced_setting);
            } else {
                // remove advanced setting here.
                PreferenceCategory preferenceCategory = (PreferenceCategory) findPreference("advanced_settings");
                if (preferenceCategory != null) {
                    screen.removePreference(preferenceCategory);
                }
            }
        }
    }
}

這裡是PrefsFragmentOne的代碼,PrefsFragmentTwo的代碼和它一樣。同時需要說明一下,當fragment resume的時候我們添加了監聽器,在fragment pause的時候我們需要反注冊監聽器。另外如果你不是像我那樣使用fragment來實現OnSharedPreferenceChangeListener,而是使用單獨的一個類(內部或者外部類)來實現它的話,你需要在你的代碼中明確持有一份這個監聽器的強引用,否則這個監聽器對象會被GC的,原因是preference manager不會包含這個監聽器的任何引用。如下代碼是有問題的代碼:

prefs.registerOnSharedPreferenceChangeListener(
  // Bad! The listener is subject to garbage collection!
  new SharedPreferences.OnSharedPreferenceChangeListener() {
  public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
    // listener implementation
  }
});

應該使用下面的代碼:

SharedPreferences.OnSharedPreferenceChangeListener listener =
    new SharedPreferences.OnSharedPreferenceChangeListener() {
  public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
    // listener implementation
  }
};
prefs.registerOnSharedPreferenceChangeListener(listener);

運行上面的代碼可以看到這樣的界面:
這裡寫圖片描述
當用戶點擊“設置鈴聲”時,界面如下:
這裡寫圖片描述
當用戶點擊“第一組列表設置”時,界面如下:
這裡寫圖片描述
當用戶點擊“第一組輸入設置”時,界面如下:
這裡寫圖片描述
當用戶點擊“顯示高級設置”時,界面如下:
這裡寫圖片描述
同時我們將這個應用運行於平板上的時候界面如下:

這裡寫圖片描述

我們看到了這個時候自動做了屏幕大小的適配,分屏顯示以充分利用屏幕(這個真的很方便)。
前面我們說道,這裡的數據會存儲在sharedpreference中,因此我們這裡進入平板模擬器(普通設備是需要root權限的)的/data/data/com.createchance.androidsettingsdemo/shared_prefs(這是android app的私有數據目錄)這個目錄下看下有什麼:
這裡寫圖片描述
我們打開com.createchance.androidsettingsdemo_preferences.xml文件看下:
這裡寫圖片描述
我們看到我們所有的設置全部保存在這裡!!並且下次我們再次進入設置界面的時候,會自動根據之前設置的值,同步界面組件的顯示。
大家有沒有感覺這個界面的風格和系統的settings應用很像?是的,settings的界面也是使用這個技術開發的,因此你的app的設置風格可以和系統的設置風格一致,這就滿足人機交互設計學上所講的“一致性”原則了!!這也是為什麼google鼓勵開發使用它開發的原因!!!

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved