page.title=Pengaturan page.tags=preference,preferenceactivity,preferencefragment @jd:body

Dalam dokumen ini

  1. Ikhtisar
    1. Preferensi
  2. Mendefinisikan Preferensi dalam XML
    1. Membuat grup pengaturan
    2. Menggunakan intent
  3. Membuat Aktivitas Preferensi
  4. Menggunakan Fragmen Preferensi
  5. Mengatur Nilai Default
  6. Menggunakan Header Preferensi
    1. Membuat file header
    2. Menampilkan header
    3. Mendukung versi yang lebih lama dengan header preferensi
  7. Preferensi Membaca
    1. Mendengarkan perubahan preferensi
  8. Mengelola Penggunaan Jaringan
  9. Membangun Preferensi Custom
    1. Menetapkan antarmuka pengguna
    2. Menyimpan nilai pengaturan
    3. Menginisialisasi nilai saat ini
    4. Menyediakan nilai default
    5. Menyimpan dan memulihkan status Preferensi

Kelas-kelas utama

  1. {@link android.preference.Preference}
  2. {@link android.preference.PreferenceActivity}
  3. {@link android.preference.PreferenceFragment}

Lihat juga

  1. Panduan desain pengaturan

Aplikasi sering kali menyertakan pengaturan yang memungkinkan pengguna memodifikasi fitur dan perilaku aplikasi. Misalnya, beberapa aplikasi memungkinkan pengguna untuk menetapkan apakah pemberitahuan diaktifkan atau menetapkan seberapa sering aplikasi menyinkronkan data dengan cloud.

Jika ingin menyediakan pengaturan untuk aplikasi, Anda harus menggunakan API Android {@link android.preference.Preference} untuk membangun antarmuka yang konsisten dengan pengalaman pengguna di aplikasi Android yang lain (termasuk pengaturan sistem). Dokumen ini menjelaskan cara membangun pengaturan aplikasi Anda menggunakan API {@link android.preference.Preference}.

Desain Pengaturan

Untuk informasi tentang cara mendesain pengaturan Anda, bacalah panduan desain Pengaturan.

Gambar 1. Cuplikan layar dari pengaturan aplikasi Messaging Android. Memilih item yang didefinisikan oleh {@link android.preference.Preference} akan membuka antarmuka untuk mengubah pengaturan.

Ikhtisar

Sebagai ganti menggunakan objek {@link android.view.View} untuk membangun antarmuka pengguna, pengaturan dibangun menggunakan berbagai subkelas dari kelas {@link android.preference.Preference} yang Anda deklarasikan dalam file XML.

Objek {@link android.preference.Preference} adalah blok pembangun untuk pengaturan tunggal. Setiap {@link android.preference.Preference} muncul sebagai item dalam daftar dan menyediakan UI yang sesuai bagi pengguna untuk memodifikasi pengaturan. Misalnya, {@link android.preference.CheckBoxPreference} membuat item daftar yang menampilkan kotak cek, dan {@link android.preference.ListPreference} membuat item yang membuka dialog berisi daftar pilihan.

Setiap {@link android.preference.Preference} yang Anda tambahkan memiliki pasangan nilai-kunci yang sesuai yang digunakan sistem untuk menyimpan pengaturan dalam file {@link android.content.SharedPreferences} default untuk pengaturan aplikasi Anda. Bila pengguna mengubah pengaturan, sistem akan memperbarui nilai yang bersangkutan dalam file {@link android.content.SharedPreferences} untuk Anda. Satu-satunya saat di mana Anda harus berinteraksi langsung dengan file {@link android.content.SharedPreferences} yang terkait adalah bila Anda perlu membaca nilai untuk menentukan perilaku aplikasi berdasarkan pengaturan pengguna.

Nilai yang tersimpan di {@link android.content.SharedPreferences} untuk setiap pengaturan bisa berupa tipe data berikut:

Oleh karena UI pengaturan aplikasi Anda dibangun menggunakan objek {@link android.preference.Preference} sebagai ganti objek {@link android.view.View}, Anda perlu menggunakan {@link android.app.Activity} khusus atau subkelas {@link android.app.Fragment} untuk menampilkan pengaturan daftar:

Cara mengatur {@link android.preference.PreferenceActivity} Anda dan instance {@link android.preference.PreferenceFragment} dibahas di bagian tentang Membuat Aktivitas Preferensi dan Menggunakan Fragmen Preferensi.

Preferensi

Setiap pengaturan untuk aplikasi Anda diwakili oleh subkelas khusus dari kelas {@link android.preference.Preference}. Setiap subkelas menyertakan seperangkat properti utama yang memungkinkan Anda untuk menetapkan berbagai hal seperti judul pengaturan dan nilai default. Setiap subkelas juga menyediakan antarmuka pengguna dan properti khusus miliknya sendiri. Misalnya, gambar 1 menampilkan cuplikan layar dari pengaturan aplikasi Messaging. Setiap item daftar dalam layar pengaturan didukung oleh objek {@link android.preference.Preference} berbeda.

Beberapa preferensi yang paling umum adalah:

{@link android.preference.CheckBoxPreference}
Menampilkan item dengan kotak cek untuk pengaturan yang diaktifkan atau dinonaktifkan. Nilai tersimpan adalah boolean (true jika diberi tanda cek).
{@link android.preference.ListPreference}
Membuka dialog berisi daftar tombol radio. Nilai tersimpan bisa berupa tipe nilai apa pun yang didukung (tercantum di atas).
{@link android.preference.EditTextPreference}
Membuka dialog berisi widget {@link android.widget.EditText}. Nilai tersimpan adalah {@link java.lang.String}.

Lihat kelas {@link android.preference.Preference} untuk mengetahui daftar subkelas lain dan propertinya.

Tentu saja, kelas bawaan tidak mengakomodasi setiap kebutuhan dan aplikasi Anda mungkin memerlukan sesuatu yang lebih khusus. Misalnya, platform saat ini tidak menyediakan kelas {@link android.preference.Preference} untuk mengambil nomor atau tanggal. Anda mungkin perlu mendefinisikan subkelas {@link android.preference.Preference} sendiri. Untuk bantuan melakukannya, lihat bagian tentang Membangun Preferensi Custom.

Mendefinisikan Preferensi dalam XML

Meskipun bisa membuat instance objek {@link android.preference.Preference} baru saat runtime, Anda harus mendefinisikan daftar pengaturan dalam XML dengan hierarki objek {@link android.preference.Preference}. Menggunakan file XML untuk mendefinisikan sekumpulan pengaturan lebih disukai karena file menyediakan struktur yang mudah dibaca dan diperbarui. Selain itu, pengaturan aplikasi Anda umumnya telah ditetapkan sebelumnya, meskipun Anda masih bisa memodifikasi kumpulan tersebut saat runtime.

Setiap subkelas {@link android.preference.Preference} bisa dideklarasikan dengan elemen XML yang cocok dengan nama kelas, seperti {@code <CheckBoxPreference>}.

Anda harus menyimpan file XML dalam direktori {@code res/xml/}. Meskipun bisa memberi nama file sesuka Anda, biasanya file diberi nama {@code preferences.xml}. Biasanya Anda hanya memerlukan satu file, karena cabang di hierarki (yang membuka daftar pengaturanny sendiri) dideklarasikan menggunakan instance tersarang {@link android.preference.PreferenceScreen}.

Catatan: Jika ingin membuat layout multipanel untuk pengaturan, Anda memerlukan file XML terpisah untuk setiap fragmen.

Simpul akar untuk file XML harus merupakan elemen {@link android.preference.PreferenceScreen <PreferenceScreen>}. Dalam elemen inilah tempat Anda menambahkan setiap {@link android.preference.Preference}. Setiap anak yang Anda tambahkan dalam elemen {@link android.preference.PreferenceScreen <PreferenceScreen>} akan tampak sebagai item tunggal dalam daftar pengaturan.

Misalnya:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <CheckBoxPreference
        android:key="pref_sync"
        android:title="@string/pref_sync"
        android:summary="@string/pref_sync_summ"
        android:defaultValue="true" />
    <ListPreference
        android:dependency="pref_sync"
        android:key="pref_syncConnectionType"
        android:title="@string/pref_syncConnectionType"
        android:dialogTitle="@string/pref_syncConnectionType"
        android:entries="@array/pref_syncConnectionTypes_entries"
        android:entryValues="@array/pref_syncConnectionTypes_values"
        android:defaultValue="@string/pref_syncConnectionTypes_default" />
</PreferenceScreen>

Dalam contoh ini, terdapat {@link android.preference.CheckBoxPreference} dan {@link android.preference.ListPreference}. Kedua item tersebut menyertakan tiga atribut berikut:

{@code android:key}
Atribut ini diperlukan untuk preferensi yang mempertahankan nilai data. Ini menetapkan kunci unik (string) yang digunakan sistem saat menyimpan nilai pengaturan ini dalam {@link android.content.SharedPreferences}.

Instance satu-satunya di mana atribut ini tidak diperlukan adalah bila preferensi berupa {@link android.preference.PreferenceCategory} atau {@link android.preference.PreferenceScreen}, atau preferensi menetapkan {@link android.content.Intent} untuk dipanggil (dengan elemen {@code <intent>}) atau {@link android.app.Fragment} untuk ditampilkan (dengan atribut {@code android:fragment}).

{@code android:title}
Ini menyediakan nama pengaturan yang bisa dilihat oleh pengguna.
{@code android:defaultValue}
Ini menetapkan nilai awal yang harus diatur sistem dalam file {@link android.content.SharedPreferences}. Anda harus memberikan nilai default untuk semua pengaturan.

Untuk informasi tentang semua atribut lain yang didukung, lihat dokumentasi {@link android.preference.Preference} (dan subkelas masing-masing).

Gambar 2. Mengatur kategori dengan judul.
1. Kategori ditetapkan oleh elemen {@link android.preference.PreferenceCategory <PreferenceCategory>}.
2. Judul ditetapkan dengan atribut {@code android:title}.

Bila daftar pengaturan Anda melebihi sekitar 10 item, Anda mungkin perlu menambahkan judul untuk mendefinisikan grup pengaturan atau menampilkan grup tersebut di layar terpisah. Opsi ini dijelaskan di bagian berikut.

Membuat grup pengaturan

Jika Anda menampilkan daftar 10 pengaturan atau lebih, pengguna mungkin akan kesulitan dalam memindai, memahami dan memprosesnya. Anda bisa mengatasinya dengan membagi sebagian atau semua pengaturan ke dalam beberapa grup, yang secara efektif akan mengubah satu daftar panjang menjadi beberapa daftar yang lebih pendek. Suatu grup pengaturan terkait bisa ditampilkan dalam salah satu dari dua cara:

Anda bisa menggunakan salah satu atau keduanya untuk mengelola pengaturan aplikasi Anda. Saat memutuskan mana yang akan digunakan dan cara membagi pengaturan, Anda harus mengikuti pedoman dalam Panduan Pengaturan Desain Android.

Menggunakan judul

Jika ingin menyediakan divider dengan heading di antara grup pengaturan (seperti yang ditampilkan dalam gambar 2), tempatkan setiap grup objek {@link android.preference.Preference} di dalam {@link android.preference.PreferenceCategory}.

Misalnya:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:title="@string/pref_sms_storage_title"
        android:key="pref_key_storage_settings">
        <CheckBoxPreference
            android:key="pref_key_auto_delete"
            android:summary="@string/pref_summary_auto_delete"
            android:title="@string/pref_title_auto_delete"
            android:defaultValue="false"... />
        <Preference
            android:key="pref_key_sms_delete_limit"
            android:dependency="pref_key_auto_delete"
            android:summary="@string/pref_summary_delete_limit"
            android:title="@string/pref_title_sms_delete"... />
        <Preference
            android:key="pref_key_mms_delete_limit"
            android:dependency="pref_key_auto_delete"
            android:summary="@string/pref_summary_delete_limit"
            android:title="@string/pref_title_mms_delete" ... />
    </PreferenceCategory>
    ...
</PreferenceScreen>

Menggunakan sublayar

Jika ingin menempatkan grup pengaturan ke dalam sublayar (seperti yang ditampilkan dalam gambar 3), tempatkan grup objek {@link android.preference.Preference} di dalam {@link android.preference.PreferenceScreen}.

Gambar 3. Mengatur sublayar. Elemen {@code <PreferenceScreen>} membuat item yang, bila dipilih, akan membuka daftar terpisah untuk menampilkan pengaturan tersarang.

Misalnya:

<PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- opens a subscreen of settings -->
    <PreferenceScreen
        android:key="button_voicemail_category_key"
        android:title="@string/voicemail"
        android:persistent="false">
        <ListPreference
            android:key="button_voicemail_provider_key"
            android:title="@string/voicemail_provider" ... />
        <!-- opens another nested subscreen -->
        <PreferenceScreen
            android:key="button_voicemail_setting_key"
            android:title="@string/voicemail_settings"
            android:persistent="false">
            ...
        </PreferenceScreen>
        <RingtonePreference
            android:key="button_voicemail_ringtone_key"
            android:title="@string/voicemail_ringtone_title"
            android:ringtoneType="notification" ... />
        ...
    </PreferenceScreen>
    ...
</PreferenceScreen>

Menggunakan intent

Dalam beberapa kasus, Anda mungkin ingin item preferensi untuk membuka beberapa aktivitas sebagai ganti layar pengaturan, seperti browser web untuk melihat halaman web. Untuk memanggil {@link android.content.Intent} saat pengguna memilih item preferensi, tambahkan elemen {@code <intent>} sebagai anak dari elemen {@code <Preference>} yang bersangkutan.

Misalnya, berikut ini cara menggunakan item preferensi untuk membuka halaman web:

<Preference android:title="@string/prefs_web_page" >
    <intent android:action="android.intent.action.VIEW"
            android:data="http://www.example.com" />
</Preference>

Anda bisa membuat intent implisit maupun eksplisit menggunakan atribut berikut:

{@code android:action}
Tindakan yang akan ditetapkan, sesuai metode {@link android.content.Intent#setAction setAction()}.
{@code android:data}
Data yang akan ditetapkan, sesuai metode {@link android.content.Intent#setData setData()}.
{@code android:mimeType}
Tipe MIME yang akan ditetapkan, sesuai metode {@link android.content.Intent#setType setType()}.
{@code android:targetClass}
Bagian kelas dari nama komponen, sesuai metode {@link android.content.Intent#setComponent setComponent()}.
{@code android:targetPackage}
Bagian paket dari nama komponen, sesuai metode {@link android.content.Intent#setComponent setComponent()}.

Membuat Aktivitas Preferensi

Untuk menampilkan pengaturan Anda dalam suatu aktivitas, perluas kelas {@link android.preference.PreferenceActivity}. Ini adalah ekstensi dari kelas {@link android.app.Activity} biasa yang menampilkan daftar pengaturan berdasarkan hierarki objek {@link android.preference.Preference}. {@link android.preference.PreferenceActivity} secara otomatis mempertahankan pengaturan yang dikaitkan dengan setiap {@link android.preference.Preference} bila pengguna membuat perubahan.

Catatan: Jika Anda mengembangkan aplikasi untuk Android 3.0 dan yang lebih tinggi, sebaiknya gunakan {@link android.preference.PreferenceFragment}. Pindah ke bagian berikutnya tentang Menggunakan Fragmen Preferensi.

Hal paling penting untuk diingat adalah jangan memuat layout tampilan selama callback {@link android.preference.PreferenceActivity#onCreate onCreate()}. Sebagai gantinya, panggil {@link android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} untuk menambahkan preferensi yang telah Anda deklarasikan dalam file XML ke aktivitas. Misalnya, berikut ini adalah kode minimum polos yang diperlukan untuk {@link android.preference.PreferenceActivity} fungsional:

public class SettingsActivity extends PreferenceActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
    }
}

Ini sebenarnya kode yang cukup untuk beberapa aplikasi, karena segera setelah pengguna memodifikasi preferensi, sistem akan menyimpan perubahan tersebut ke file {@link android.content.SharedPreferences} default yang bisa dibaca oleh komponen aplikasi Anda lainnya bila Anda perlu memeriksa pengaturan pengguna. Akan tetapi, banyak aplikasi, yang memerlukan kode lebih sedikit untuk mendengarkan perubahan yang terjadi pada preferensi. Untuk informasi tentang mendengarkan perubahan di file {@link android.content.SharedPreferences}, lihat bagian tentang Preferensi Membaca.

Menggunakan Fragmen Preferensi

Jika Anda mengembangkan Android 3.0 (API level 11) dan yang lebih tinggi, Anda harus menggunakan {@link android.preference.PreferenceFragment} untuk menampilkan daftar objek {@link android.preference.Preference} Anda. Anda bisa menambahkan {@link android.preference.PreferenceFragment} ke aktivitas apa pun,—Anda tidak perlu menggunakan {@link android.preference.PreferenceActivity}.

Fragmen menyediakan arsitektur yang lebih fleksibel untuk aplikasi Anda, dibandingkan hanya menggunakan aktivitas, apa pun jenis aktivitas yang Anda bangun. Dengan sendirinya, kami menyarankan Anda menggunakan {@link android.preference.PreferenceFragment} untuk mengontrol tampilan pengaturan Anda sebagai ganti {@link android.preference.PreferenceActivity} bila memungkinkan.

Implementasi {@link android.preference.PreferenceFragment} Anda bisa semudah mendefinisikan metode {@link android.preference.PreferenceFragment#onCreate onCreate()} untuk memuat file preferensi dengan {@link android.preference.PreferenceFragment#addPreferencesFromResource addPreferencesFromResource()}. Misalnya:

public static class SettingsFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.preferences);
    }
    ...
}

Anda nanti bisa menambahkan fragmen ini ke {@link android.app.Activity} seperti yang Anda lakukan untuk {@link android.app.Fragment} lainnya. Misalnya:

public class SettingsActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Display the fragment as the main content.
        getFragmentManager().beginTransaction()
                .replace(android.R.id.content, new SettingsFragment())
                .commit();
    }
}

Catatan: {@link android.preference.PreferenceFragment} tidak memiliki objek {@link android.content.Context} sendiri. Jika memerlukan objek {@link android.content.Context} , Anda bisa memanggil {@link android.app.Fragment#getActivity()}. Akan tetapi, berhati-hatilah untuk memanggil {@link android.app.Fragment#getActivity()} hanya bila fragmen telah dikaitkan dengan aktivitas. Bila fragmen belum dikaitkan, atau terlepas saat akhir daur hidupnya, {@link android.app.Fragment#getActivity()} akan mengembalikan nol.

Mengatur Nilai Default

Preferensi yang Anda buat mungkin mendefinisikan beberapa perilaku penting untuk aplikasi, jadi Anda perlu menginisialisasi file {@link android.content.SharedPreferences} yang terkait dengan nilai default untuk setiap {@link android.preference.Preference} bila pengguna menggunakan aplikasi Anda untuk pertama kali.

Hal pertama yang harus Anda lakukan adalah menetapkan nilai default untuk setiap objek {@link android.preference.Preference} di file XML Anda menggunakan atribut {@code android:defaultValue}. Nilainya bisa berupa tipe data apa saja yang sesuai untuk objek {@link android.preference.Preference} bersangkutan. Misalnya:

<!-- default value is a boolean -->
<CheckBoxPreference
    android:defaultValue="true"
    ... />

<!-- default value is a string -->
<ListPreference
    android:defaultValue="@string/pref_syncConnectionTypes_default"
    ... />

Kemudian, dari metode {@link android.app.Activity#onCreate onCreate()} dalam aktivitas utama aplikasi Anda—dan dalam aktivitas lainnya yang digunakan pengguna untuk masuk ke aplikasi Anda untuk pertama kali —panggil {@link android.preference.PreferenceManager#setDefaultValues setDefaultValues()}:

PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);

Memanggil ini selama {@link android.app.Activity#onCreate onCreate()} akan memastikan aplikasi Anda diinisialisasi dengan pengaturan default, yang mungkin perlu dibaca oleh aplikasi Anda untuk menentukan beberapa perilaku (seperti apakah akan mengunduh data pada jaringan seluler).

Metode ini membutuhkan tiga argumen:

Selama Anda mengatur argumen ketiga ke false, Anda bisa dengan aman memanggil metode ini setiap kali aktivitas Anda memulai tanpa mengesampingkan preferensi tersimpan pengguna dengan mengatur ulang preferensi tersebut ke default. Akan tetapi, jika mengatur ke true, Anda akan mengesampingkan nilai sebelumnya dengan default.

Menggunakan Header Preferensi

Dalam kasus yang jarang terjadi, Anda mungkin perlu mendesain pengaturan agar layar pertama hanya menampilkan daftar sublayar (seperti dalam aplikasi Setting pada sistem, seperti yang ditampilkan dalam gambar 4 dan 5). Bila mengembangkan desain seperti itu untuk Android 3.0 dan yang lebih tinggi, Anda harus menggunakan fitur "header" yang baru di Android 3.0, sebagai ganti membangun sublayar dengan elemen {@link android.preference.PreferenceScreen} tersarang.

Untuk membangun pengaturan dengan header, Anda perlu:

  1. Memisahkan setiap grup pengaturan ke dalam instance {@link android.preference.PreferenceFragment} terpisah. Ini berarti, setiap grup pengaturan memerlukan file XML terpisah.
  2. Membuat file header XML yang mencantumkan daftar setiap grup pengaturan dan mendeklarasikan fragmen mana yang berisi daftar pengaturan yang sesuai.
  3. Memperluas kelas {@link android.preference.PreferenceActivity} untuk menjadi host pengaturan Anda.
  4. Mengimplementasikan callback {@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} untuk menetapkan file header.

Manfaat besar dalam menggunakan desain ini adalah karena {@link android.preference.PreferenceActivity} secara otomatis akan menampilkan layout dua panel yang ditampilkan dalam gambar 4 bila dijalankan pada layar besar.

Bahkan jika aplikasi Anda mendukung versi Android yang lebih lama dari 3.0, Anda bisa membangun aplikasi untuk menggunakan {@link android.preference.PreferenceFragment} bagi presentasi dua panel pada perangkat yang lebih baru sementara tetap mendukung hierarki multilayar biasa pada perangkat yang lebih lama (lihat bagian tentang Mendukung versi yang lebih lama dengan header preferensi).

Gambar 4. Layout dua panel dengan header.
1. Header didefinisikan dengan file header XML.
2. Setiap grup pengaturan didefinisikan dengan {@link android.preference.PreferenceFragment} yang ditetapkan oleh elemen {@code <header>} dalam file header.

Gambar 5. Perangkat handset dengan header pengaturan. Bila sebuah item dipilih, {@link android.preference.PreferenceFragment} terkait akan menggantikan header.

Membuat file header

Setiap grup pengaturan dalam daftar header Anda akan ditetapkan oleh elemen {@code <header>} tunggal dalam elemen {@code <preference-headers>} akar. Misalnya:

<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
    <header
        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
        android:title="@string/prefs_category_one"
        android:summary="@string/prefs_summ_category_one" />
    <header
        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
        android:title="@string/prefs_category_two"
        android:summary="@string/prefs_summ_category_two" >
        <!-- key/value pairs can be included as arguments for the fragment. -->
        <extra android:name="someKey" android:value="someHeaderValue" />
    </header>
</preference-headers>

Dengan atribut {@code android:fragment}, setiap header mendeklarasikan instance {@link android.preference.PreferenceFragment} yang harus terbuka saat pengguna memilih header.

Elemen {@code <extras>} memungkinkan Anda meneruskan pasangan nilai-kunci ke fragmen di {@link android.os.Bundle}. Fragmen bisa mengambil argumen dengan memanggil {@link android.app.Fragment#getArguments()}. Anda bisa meneruskan argumen ke fragmen dengan berbagai alasan, namun satu alasan yang baik adalah untuk menggunakan kembali subkelas yang sama dari {@link android.preference.PreferenceFragment} untuk setiap grup dan menggunakan argumen untuk menetapkan file XML preferensi mana yang harus dimuat fragmen.

Misalnya, ada fragmen yang bisa digunakan ulang untuk berbagai grup pengaturan, bila setiap header mendefinisikan argumen {@code <extra>} dengan kunci {@code "settings"}:

public static class SettingsFragment extends PreferenceFragment {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        String settings = getArguments().getString("settings");
        if ("notifications".equals(settings)) {
            addPreferencesFromResource(R.xml.settings_wifi);
        } else if ("sync".equals(settings)) {
            addPreferencesFromResource(R.xml.settings_sync);
        }
    }
}

Menampilkan header

Untuk menampilkan header preferensi, Anda harus mengimplementasikan metode callback {@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} dan memanggil {@link android.preference.PreferenceActivity#loadHeadersFromResource loadHeadersFromResource()}. Misalnya:

public class SettingsActivity extends PreferenceActivity {
    @Override
    public void onBuildHeaders(List<Header> target) {
        loadHeadersFromResource(R.xml.preference_headers, target);
    }
}

Bila pengguna memilih item dari daftar header, sistem akan membuka {@link android.preference.PreferenceFragment} terkait.

Catatan: Saat menggunakan header preferensi, subkelas {@link android.preference.PreferenceActivity} Anda tidak perlu mengimplementasikan metode {@link android.preference.PreferenceActivity#onCreate onCreate()}, karena tugas yang diperlukan untuk aktivitas hanyalah memuat header.

Mendukung versi yang lebih lama dengan header preferensi

Jika aplikasi Anda mendukung versi Android yang lebih lama dari 3.0, Anda tetap bisa menggunakan header untuk menyediakan layout dua panel saat berjalan pada Android 3.0 dan yang lebih tinggi. Anda hanya perlu membuat file XML preferensi tambahan yang menggunakan elemen {@link android.preference.Preference <Preference>} dasar yang berperilaku seperti item header (untuk digunakan oleh Android versi yang lebih lama).

Akan tetapi, sebagai ganti membuka {@link android.preference.PreferenceScreen} baru, setiap elemen {@link android.preference.Preference <Preference>} mengirimkan {@link android.content.Intent} ke {@link android.preference.PreferenceActivity} yang menetapkan file XML preferensi mana yang akan dimuat.

Misalnya, ini adalah file XML untuk header preferensi yang menggunakan Android 3.0 dan yang lebih tinggi ({@code res/xml/preference_headers.xml}):

<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
    <header
        android:fragment="com.example.prefs.SettingsFragmentOne"
        android:title="@string/prefs_category_one"
        android:summary="@string/prefs_summ_category_one" />
    <header
        android:fragment="com.example.prefs.SettingsFragmentTwo"
        android:title="@string/prefs_category_two"
        android:summary="@string/prefs_summ_category_two" />
</preference-headers>

Dan ini adalah file preferensi yang menyediakan header yang sama untuk versi yang lebih lama dari Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <Preference
        android:title="@string/prefs_category_one"
        android:summary="@string/prefs_summ_category_one"  >
        <intent
            android:targetPackage="com.example.prefs"
            android:targetClass="com.example.prefs.SettingsActivity"
            android:action="com.example.prefs.PREFS_ONE" />
    </Preference>
    <Preference
        android:title="@string/prefs_category_two"
        android:summary="@string/prefs_summ_category_two" >
        <intent
            android:targetPackage="com.example.prefs"
            android:targetClass="com.example.prefs.SettingsActivity"
            android:action="com.example.prefs.PREFS_TWO" />
    </Preference>
</PreferenceScreen>

Karena dukungan untuk {@code <preference-headers>} telah ditambahkan di Android 3.0, sistem akan memanggil {@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} di {@link android.preference.PreferenceActivity} hanya saat berjalan pada Android 3.0 atau yang lebih tinggi. Untuk memuat file header "lama" ({@code preference_headers_legacy.xml}), Anda harus memeriksa versi Android dan, jika versi tersebut lebih lama dari Android 3.0 ({@link android.os.Build.VERSION_CODES#HONEYCOMB}), panggil {@link android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} untuk memuat file header lama. Misalnya:

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

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        // Load the legacy preferences headers
        addPreferencesFromResource(R.xml.preference_headers_legacy);
    }
}

// Called only on Honeycomb and later
@Override
public void onBuildHeaders(List<Header> target) {
   loadHeadersFromResource(R.xml.preference_headers, target);
}

Satu-satunya hal yang perlu dilakukan adalah menangani {@link android.content.Intent} yang diteruskan ke aktivitas untuk mengidentifikasi file preferensi yang akan dimuat. Jadi ambillah tindakan intent dan bandingkan dengan string tindakan yang diketahui yang telah Anda gunakan dalam tag {@code <intent>} XML preferensi:

final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE";
...

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

    String action = getIntent().getAction();
    if (action != null && action.equals(ACTION_PREFS_ONE)) {
        addPreferencesFromResource(R.xml.preferences);
    }
    ...

    else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
        // Load the legacy preferences headers
        addPreferencesFromResource(R.xml.preference_headers_legacy);
    }
}

Ketahuilah bahwa panggilan berturut-turut ke {@link android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} akan menumpuk semua preferensi ke dalam satu daftar, jadi pastikan bahwa ini hanya dipanggil sekali dengan mengikatkan syarat ke pernyataan else-if.

Preferensi Membaca

Secara default, semua preferensi aplikasi Anda disimpan ke file yang bisa diakses dari mana saja di dalam aplikasi dengan memanggil metode statis {@link android.preference.PreferenceManager#getDefaultSharedPreferences PreferenceManager.getDefaultSharedPreferences()}. Ini akan mengembalikan objek {@link android.content.SharedPreferences} berisi semua pasangan nilai-kunci yang terkait dengan objek {@link android.preference.Preference} yang digunakan di {@link android.preference.PreferenceActivity} Anda.

Misalnya, inilah cara membaca salah satu nilai preferensi dari aktivitas lain dalam aplikasi Anda:

SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "");

Mendengarkan perubahan preferensi

Ada beberapa alasan yang membuat Anda perlu mendapatkan pemberitahuan segera setelah pengguna mengubah salah satu preferensi. Untuk menerima callback saat perubahan terjadi pada salah satu preferensi, implementasikan antarmuka {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener SharedPreference.OnSharedPreferenceChangeListener} dan daftarkan listener untuk objek {@link android.content.SharedPreferences} dengan memanggil {@link android.content.SharedPreferences#registerOnSharedPreferenceChangeListener registerOnSharedPreferenceChangeListener()}.

Antarmuka hanya memiliki satu metode callback, {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged onSharedPreferenceChanged()}, dan mungkin lebih mudah mengimplementasikan antarmuka sebagai bagian dari aktivitas Anda. Misalnya:

public class SettingsActivity extends PreferenceActivity
                              implements OnSharedPreferenceChangeListener {
    public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType";
    ...

    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
        String key) {
        if (key.equals(KEY_PREF_SYNC_CONN)) {
            Preference connectionPref = findPreference(key);
            // Set summary to be the user-description for the selected value
            connectionPref.setSummary(sharedPreferences.getString(key, ""));
        }
    }
}

Dalam contoh ini, metode akan memeriksa apakah pengaturan yang diubah adalah untuk kunci preferensi yang diketahui. Ini akan memanggil {@link android.preference.PreferenceActivity#findPreference findPreference()} untuk mendapatkan objek {@link android.preference.Preference} yang diubah agar bisa memodifikasi rangkuman item menjadi keterangan pada pilihan pengguna. Ini berarti, bila pengaturan adalah {@link android.preference.ListPreference} atau pengaturan multipilihan, Anda harus memanggil {@link android.preference.Preference#setSummary setSummary()} bila pengaturan berubah ke tampilkan status saat ini (seperti pengaturan Sleep yang ditampilkan dalam gambar 5).

Catatan: Seperti dijelaskan dalam dokumen Desain Android tentang Pengaturan, kami merekomendasikan Anda untuk memperbarui rangkuman {@link android.preference.ListPreference} setiap kali pengguna mengubah preferensi untuk menjelaskan pengaturan saat ini.

Untuk manajemen daur hidup yang baik di aktivitas, kami merekomendasikan Anda untuk mendaftarkan dan mencabut pendaftaran {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener} selama callback {@link android.app.Activity#onResume} dan {@link android.app.Activity#onPause}:

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

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

Perhatian: Bila Anda memanggil {@link android.content.SharedPreferences#registerOnSharedPreferenceChangeListener registerOnSharedPreferenceChangeListener()}, pengelola preferensi saat ini tidak akan menyimpan referensi kuat ke listener. Anda harus menyimpan referensi kuat bagi listener, atau referensi akan rentan terhadap pengumpulan sampah. Kami merekomendasikan Anda untuk mempertahankan referensi bagi listener dalam data instance objek yang akan ada selama Anda memerlukan listener tersebut.

Misalnya, dalam kode berikut, caller tidak menyimpan referensi ke listener. Akibatnya, listener akan dikenakan pengumpulan sampah, dan suatu saat nanti akan gagal:

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

Sebagai gantinya, simpan referensi ke listener dalam bidang data instance objek yang akan ada selama listener dibutuhkan:

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

Mengelola Penggunaan Jaringan

Mulai Android 4.0, aplikasi Settings untuk sistem memungkinkan pengguna melihat seberapa besar data jaringan yang digunakan aplikasi mereka saat berada di latar depan dan latar belakang. Kemudian pengguna bisa menonaktifkan penggunaan data latar belakang untuk aplikasi individual. Agar pengguna tidak menonaktifkan akses aplikasi ke data dari latar belakang, Anda harus menggunakan koneksi data secara efisien dan mengizinkan pengguna untuk menyaring penggunaan data aplikasi melalui pengaturan aplikasi Anda.

Misalnya, Anda bisa mengizinkan pengguna untuk mengontrol seberapa sering aplikasi menyinkronkan data, apakah aplikasi hanya melakukan pengunggahan/pengunduhan bila ada Wi-Fi, apakah aplikasi menggunakan data saat roaming, dll. Dengan tersedianya kontrol ini bagi pengguna, mereka kemungkinan besar tidak akan menonaktifkan akses aplikasi ke data saat mendekati batas yang mereka tetapkan dalam Settings pada sistem, karena mereka bisa mengontrol secara tepat seberapa besar data yang digunakan aplikasi Anda.

Setelah menambahkan preferensi yang diperlukan dalam {@link android.preference.PreferenceActivity} Anda untuk mengontrol kebiasaan data aplikasi, Anda harus menambahkan filter intent untuk {@link android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} dalam file manifes Anda. Misalnya:

<activity android:name="SettingsActivity" ... >
    <intent-filter>
       <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
       <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

Filter intent ini menunjukkan pada sistem bahwa ini adalah aktivitas yang mengontrol penggunaan data aplikasi Anda. Jadi, saat pengguna memeriksa seberapa banyak data yang digunakan oleh aplikasi dari aplikasi Settings pada sistem, tombol View application settings akan tersedia dan menjalankan {@link android.preference.PreferenceActivity} sehingga pengguna bisa menyaring seberapa besar data yang digunakan aplikasi Anda.

Membangun Preferensi Custom

Kerangka kerja Android menyertakan berbagai subkelas {@link android.preference.Preference} yang memungkinkan Anda membangun UI untuk beberapa macam tipe pengaturan. Akan tetapi, Anda mungkin menemukan pengaturan yang diperlukan bila tidak ada solusi bawaan, seperti picker nomor atau picker tanggal. Dalam hal demikian, Anda akan perlu membuat preferensi custom dengan memperluas kelas {@link android.preference.Preference} atau salah satu subkelas lainnya.

Bila memperluas kelas {@link android.preference.Preference}, ada beberapa hal penting yang perlu Anda lakukan:

Bagian berikut menjelaskan cara melakukan setiap tugas ini.

Menetapkan antarmuka pengguna

Jika secara langsung memperluas kelas {@link android.preference.Preference}, Anda perlu mengimplementasikan {@link android.preference.Preference#onClick()} untuk mendefinisikan tindakan yang terjadi bila pengguna memilih item tersebut. Akan tetapi, sebagian besar pengaturan custom memperluas {@link android.preference.DialogPreference} untuk menampilkan dialog, sehingga menyederhanakan prosedur. Bila memperluas {@link android.preference.DialogPreference}, Anda harus memanggil {@link android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()} selama di konstruktor kelas untuk menetapkan layout dialog.

Misalnya, beri ini konstruktor untuk {@link android.preference.DialogPreference} custom yang mendeklarasikan layout dan menetapkan teks untuk tombol dialog negatif dan positif default:

public class NumberPickerPreference extends DialogPreference {
    public NumberPickerPreference(Context context, AttributeSet attrs) {
        super(context, attrs);

        setDialogLayoutResource(R.layout.numberpicker_dialog);
        setPositiveButtonText(android.R.string.ok);
        setNegativeButtonText(android.R.string.cancel);

        setDialogIcon(null);
    }
    ...
}

Menyimpan nilai pengaturan

Anda bisa menyimpan nilai pengaturan kapan saja dengan memanggil salah satu metode {@code persist*()} kelas {@link android.preference.Preference}, seperti {@link android.preference.Preference#persistInt persistInt()} jika nilai pengaturan adalah integer atau {@link android.preference.Preference#persistBoolean persistBoolean()} untuk menyimpan boolean.

Catatan: Setiap {@link android.preference.Preference} hanya bisa menyimpan satu tipe data, jadi Anda harus menggunakan metode {@code persist*()} yang tepat untuk tipe data yang digunakan oleh {@link android.preference.Preference} custom Anda.

Bila Anda memilih untuk mempertahankannya, pengaturan bisa bergantung pada kelas {@link android.preference.Preference} yang Anda perluas. Jika Anda memperluas {@link android.preference.DialogPreference}, maka Anda harus mempertahankan nilai hanya jika dialog tertutup karena hasil positif (pengguna memilih tombol "OK").

Bila {@link android.preference.DialogPreference} tertutup, sistem akan memanggil metode {@link android.preference.DialogPreference#onDialogClosed onDialogClosed()}. Metode mencakup argumen boolean yang menetapkan apakah hasil pengguna "positif"—jika nilainya true, maka pengguna memilih tombol positif dan Anda harus menyimpan nilai baru. Misalnya:

@Override
protected void onDialogClosed(boolean positiveResult) {
    // When the user selects "OK", persist the new value
    if (positiveResult) {
        persistInt(mNewValue);
    }
}

Dalam contoh ini, mNewValue adalah anggota kelas yang menampung nilai pengaturan saat ini. Memanggil {@link android.preference.Preference#persistInt persistInt()} akan menyimpan nilai ke file {@link android.content.SharedPreferences} (secara otomatis menggunakan kunci yang ditetapkan dalam file XML untuk {@link android.preference.Preference} ini).

Menginisialisasi nilai saat ini

Bila sistem menambahkan {@link android.preference.Preference} Anda ke layar, ia akan memanggil {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} untuk memberi tahu Anda apakah pengaturan memiliki nilai yang dipertahankan. Jika tidak ada nilai yang dipertahankan, panggilan ini akan menyediakan nilai default bagi Anda.

Metode {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} akan meneruskan boolean, restorePersistedValue, untuk menunjukkan apakah nilai dipertahankan untuk pengaturan. Jika true, maka Anda harus mengambil nilai yang dipertahankan dengan memanggil salah satu metode {@code getPersisted*()} kelas {@link android.preference.Preference}, seperti {@link android.preference.Preference#getPersistedInt getPersistedInt()} untuk nilai integer. Anda biasanya perlu mengambil nilai yang dipertahankan agar bisa memperbarui UI dengan benar untuk merefleksikan nilai yang tersimpan sebelumnya.

Jika restorePersistedValue adalah false, maka Anda harus menggunakan nilai default yang diteruskan dalam argumen kedua.

@Override
protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
    if (restorePersistedValue) {
        // Restore existing state
        mCurrentValue = this.getPersistedInt(DEFAULT_VALUE);
    } else {
        // Set default state from the XML attribute
        mCurrentValue = (Integer) defaultValue;
        persistInt(mCurrentValue);
    }
}

Setiap metode {@code getPersisted*()} memerlukan argumen yang menetapkan nilai default untuk digunakan jika tidak ada nilai yang dipertahankan atau kunci tidak ada. Dalam contoh di atas, konstanta lokal yang digunakan untuk menetapkan nilai default dalam kasus {@link android.preference.Preference#getPersistedInt getPersistedInt()} tidak bisa mengembalikan nilai yang dipertahankan.

Perhatian: Anda tidak bisa menggunakan defaultValue sebagai nilai default dalam metode {@code getPersisted*()}, karena nilainya selalu nol bila restorePersistedValue adalah true.

Menyediakan nilai default

Jika instance kelas {@link android.preference.Preference} Anda menetapkan nilai default (dengan atribut {@code android:defaultValue}), maka sistem akan memanggil {@link android.preference.Preference#onGetDefaultValue onGetDefaultValue()} bila membuat instance objek untuk mengambil nilai. Anda harus mengimplementasikan metode ini agar sistem bisa menyimpan nilai default dalam {@link android.content.SharedPreferences}. Misalnya:

@Override
protected Object onGetDefaultValue(TypedArray a, int index) {
    return a.getInteger(index, DEFAULT_VALUE);
}

Argumen metode menyediakan semua hal yang Anda perlukan: larik atribut dan posisi indeks dari {@code android:defaultValue}, yang harus Anda ambil. Alasan Anda harus mengimplementasikan metode ini untuk mengekstrak nilai default dari atribut adalah karena Anda harus menetapkan nilai default lokal untuk atribut jika nilai tidak didefinisikan.

Menyimpan dan memulihkan status Preferensi

Seperti halnya {@link android.view.View} di layout, subkelas {@link android.preference.Preference} Anda bertanggung jawab menyimpan dan memulihkan statusnya jika aktivitas atau fragmen di-restart (seperti saat pengguna memutar layar). Untuk menyimpan dan memulihkan status kelas {@link android.preference.Preference} dengan benar, Anda harus mengimplementasikan metode callback daur hidup {@link android.preference.Preference#onSaveInstanceState onSaveInstanceState()} dan {@link android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}.

Status {@link android.preference.Preference} Anda didefinisikan oleh objek yang mengimplementasikan antarmuka {@link android.os.Parcelable}. Kerangka kerja Android menyediakan objek seperti itu untuk Anda gunakan sebagai titik mulai untuk mendefinisikan objek status Anda: kelas {@link android.preference.Preference.BaseSavedState}.

Untuk mendefinisikan cara kelas {@link android.preference.Preference} menyimpan statusnya, Anda harus memperluas kelas {@link android.preference.Preference.BaseSavedState}. Anda hanya perlu mengesampingkan beberapa metode dan mendefinisikan objek {@link android.preference.Preference.BaseSavedState#CREATOR} .

Untuk sebagian besar aplikasi, Anda bisa menyalin implementasi berikut dan cukup mengubah baris yang menangani {@code value} jika subkelas {@link android.preference.Preference} Anda menyimpan tipe data selain integer.

private static class SavedState extends BaseSavedState {
    // Member that holds the setting's value
    // Change this data type to match the type saved by your Preference
    int value;

    public SavedState(Parcelable superState) {
        super(superState);
    }

    public SavedState(Parcel source) {
        super(source);
        // Get the current preference's value
        value = source.readInt();  // Change this to read the appropriate data type
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        super.writeToParcel(dest, flags);
        // Write the preference's value
        dest.writeInt(value);  // Change this to write the appropriate data type
    }

    // Standard creator object using an instance of this class
    public static final Parcelable.Creator<SavedState> CREATOR =
            new Parcelable.Creator<SavedState>() {

        public SavedState createFromParcel(Parcel in) {
            return new SavedState(in);
        }

        public SavedState[] newArray(int size) {
            return new SavedState[size];
        }
    };
}

Dengan implementasi {@link android.preference.Preference.BaseSavedState} di atas yang ditambahkan ke aplikasi Anda (biasanya sebagai subkelas dari subkelas {@link android.preference.Preference}), Anda nanti perlu mengimplementasikan metode {@link android.preference.Preference#onSaveInstanceState onSaveInstanceState()} dan {@link android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} untuk subkelas {@link android.preference.Preference} Anda.

Misalnya:

@Override
protected Parcelable onSaveInstanceState() {
    final Parcelable superState = super.onSaveInstanceState();
    // Check whether this Preference is persistent (continually saved)
    if (isPersistent()) {
        // No need to save instance state since it's persistent,
        // use superclass state
        return superState;
    }

    // Create instance of custom BaseSavedState
    final SavedState myState = new SavedState(superState);
    // Set the state's value with the class member that holds current
    // setting value
    myState.value = mNewValue;
    return myState;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
    // Check whether we saved the state in onSaveInstanceState
    if (state == null || !state.getClass().equals(SavedState.class)) {
        // Didn't save the state, so call superclass
        super.onRestoreInstanceState(state);
        return;
    }

    // Cast state to custom BaseSavedState and pass to superclass
    SavedState myState = (SavedState) state;
    super.onRestoreInstanceState(myState.getSuperState());

    // Set this Preference's widget to reflect the restored state
    mNumberPicker.setValue(myState.value);
}