
Ekran ustawień to jeden z najważniejszych widoków w aplikacji. Android przecież słynie z tego, że posiada on mnóstwo konfiguracji. My również powinniśmy o tym pamiętać, tym bardziej, że tworzenie tej części programu jest bardzo proste (w porównaniu do reszty kodu), a zalety korzystania z tego są całkiem spore.
Informacja: Nie radzisz sobie z kodem? Coś Ci nie wychodzi lub nie działa? Zgubiłeś się? W tym miejscu zobaczysz pełen kod aplikacji.
1. Preference

Do budowania ustawień w programie używamy API z systemu o nazwie
Preference. Jest to interfejs, który używamy
w samym pliku z konfiguracją bloków (blok - element na liście opcji). Aby program mógł taką listę obsłużyć, naszą klasę z ekranem ustawień musimy rozszerzyć o
PreferenceActivity lub/i
PreferenceFragment. Tutaj należy się ograniczać, bo duża liczba opcji w tym ekranie może przerazić użytkownika (nikt nie chce spędzić całego dnia na analizę każdej opcji). Jak dobrze tym zarządzać macie opisane w
Android Design Guidelines.
Kolejne opcje budujemy używając odpowiednich subklas w pliku
XML. I tak
Preference to pojedynczy, podstawowy blok, który widzimy w tym oknie.
Może on występować pod różnymi postaciami, na przykład jako checkbox (
CheckboxPreference) albo lista (
ListPreference).
Ważnym atrybutem w każdym
Preference jest
klucz.
To po nim dostajemy się do wartości wybranego pola, a następnie stosujemy wybrany algorytm. Zazwyczaj odbieramy prostą odpowiedź typu
true, ale czasami (na przykład w dużych listach wyboru) musimy stworzyć tablicę w pliku
/arrays.xml, która będzie nam służyć jako lista z wartościami i pozycjami do wybrania.
Każdy z elementów w
Preference jest zapisywany do wewnętrznej pamięci aplikacji, która nazywa się
SharedPreferences. Tutaj kolejna ważna uwaga -
każda zmiana ustawień odbywa się z automatycznym zapisem, to znaczy kiedy my zmieniamy wartość w tym ekranie i wyjdziemy z aplikacji, to wracając ponownie do programu mamy zaznaczony ostatni wybór. Nie musimy dbać o zapisywanie tych wartości, całość dzieje się w locie, bez naszego udziału. Oczywiście,
jeżeli potrzebujemy ręcznej zamiany wartości danego klucza to możemy to zrobić bez najmniejszego problemu (i nadal w ustawieniach będzie widać aktualne zaznaczenie).
W
SharedPreferences możemy zapisywać wartości takie jak:
- Int (liczba całkowita)
- Float (liczba rzeczywista)
- Boolean (prawda lub fałsz)
- Long
- String
- String set
Musimy o tym pamiętać, budując własną konfigurację. Innych elementów w tej części systemu nie możemy przechowywać.
Niestety, samo
Preference nie wystarczy do sprawnego działania. Jak wcześniej pisałem, specjalna budowa ustaweń musi być rozpoznawalna przez nasze
Activity. I tak aby zapewnić wsparcie dla starszych wersji systemu (to znaczy aby po wejściu do ustawień aplikacja działała), musimy używać
PreferenceActivity. Za to
PreferenceFragment jest rozszerzeniem dla nowszych wersji Androida (od 4.0) i działa nieco inaczej (ale o tym jeszcze nie dziś).
2. Preference(s)
Analizując pojedynczy blok w ustawieniach -
każdy z elementów ma swoje własne atrybuty, według których odpowiednio widzimy go na liście. Może być to nazwa, opis pod spodem, typ pola, tablica z wartościami, domyślne zaznaczenie i tak dalej... Najczęściej używanymi blokami są:
- CheckBoxPreference, czyli pojedyncze pole z możliwością zaznaczenia lub odznaczenia. Wykorzystuje rzecz jasna typ Boolean jako wartość, więc może mieć tylko dwa stany.
- ListPreference, czyli lista wyboru. Otwiera dialog z opcjami do wyboru, gdzie możemy (w zależności od samej listy) wybrać jeden element lub kilka. Swoją wartość zazwyczaj zapisuje jako liczbę, ale może być to również ciąg znaków.
- EditTextPreference, czyli dialog z polem do wpisania dowolnego tekstu. Zapisuje się jako String.
Jeżeli podstawowe elementy ustawień nas nie satysfakcjonują, zawsze
możemy stworzyć własne. Nadal jednak należy pamiętać o typach, jakie
SharedPreferences może przetrzymywać.
3. Definiujemy!
Przejdźmy do stworzenia prostych ustawień. Użyjemy każdego z powyższych pól, aby przedstawić ich działanie. Nie jest to trudne i zajmuje tylko chwilę.

Wiecie, że
Preference definiujemy w pliku
XML. Nie znajduje się on jednak w katalogu /layout, a swoim własnym -
/xml. Jeżeli go nie mamy, to powinniśmy stworzyć. Nazwa pliku jest dowolna, zazwyczaj jednak stosuje się tytuł
preferences.xml.
Tworzymy więc ten plik, a w nim dodajemy nasze elementy:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_checkbox"
android:summary="Otrzymujemy true albo false"
android:title="Checkbox" />
<EditTextPreference
android:dialogTitle="EditText"
android:key="pref_edittext"
android:summary="Dowolna, wpisana wartość"
android:title="EditText" />
<ListPreference
android:dialogTitle="Nasza lista"
android:entries="@array/przykladowa_lista"
android:entryValues="@array/przykladowa_lista_wartosci"
android:summary="Zwraca liczbę lub string"
android:key="pref_list"
android:title="Lista" />
</PreferenceScreen>
Od razu możemy zauważyć
charakterystyczne atrybuty jak key, title i defaultValue. Ich nazwa mówi sama za siebie i raczej wiadomo do czego każdy z nich służy. Oczywiście
samych atrybutów jest więcej.
Jeżeli chcemy stworzyć dużą liczbę ustawień, to dobrym rozwiązaniem będzie
stworzenie nagłówka dla każdej sekcji. Te nazywamy grupami, i w przeciwieństwie do powyższego przykładu,
nie tworzymy całości pod sobą, a dopisujemy do wyznaczonej części - PreferenceCategory. Jednym z atrybutów tego elementu jest oczywiście nazwa grupy.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="Przykładowa grupa" >
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_checkbox"
android:summary="Otrzymujemy true albo false"
android:title="Checkbox" />
</PreferenceCategory>
<EditTextPreference
android:dialogTitle="EditText"
android:key="pref_edittext"
android:summary="Dowolna, wpisana wartość"
android:title="EditText" />
<ListPreference
android:dialogTitle="Nasza lista"
android:entries="@array/przykladowa_lista"
android:entryValues="@array/przykladowa_lista_wartosci"
android:key="pref_list"
android:summary="Zwraca liczbę lub string"
android:title="Lista" />
</PreferenceScreen>
Czasami w ustawieniach możemy zauważyć jeszcze jeden typ
Preference - taki, w którym po wybraniu go przechodzimy do kolejnego ekranu. To może być cecha
PreferenceFragment, ale również i
PreferenceScreen - specjalnego tagu to pokazywania opcji w oddzielnym oknie. Implementacja wygląda podobnie jak w innych tagach.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory android:title="Przykładowa grupa" >
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_checkbox"
android:summary="Otrzymujemy true albo false"
android:title="Checkbox" />
</PreferenceCategory>
<EditTextPreference
android:dialogTitle="EditText"
android:key="pref_edittext"
android:summary="Dowolna, wpisana wartość"
android:title="EditText" />
<ListPreference
android:dialogTitle="Nasza lista"
android:entries="@array/przykladowa_lista"
android:entryValues="@array/przykladowa_lista_wartosci"
android:key="pref_list"
android:summary="Zwraca liczbę lub string"
android:title="Lista" />
<PreferenceScreen
android:persistent="false"
android:title="PreferenceScreen" >
<CheckBoxPreference
android:defaultValue="true"
android:key="pref_preferencescreen_checkbox"
android:summary="Otrzymujemy true albo false"
android:title="Checkbox" />
</PreferenceScreen>
</PreferenceScreen>
Kod
XML już mamy, teraz czas na opisanie
PreferenceActivity. Tworzymy nową klasę w naszej paczce, o nazwie na przykład
View_Preference. Powinniście sobie od razu poradzić, bo implementacja wygląda jak w normalnym
Activtiy. Jeżeli jednak nie wiecie o co chodzi, to mój kod macie poniżej:
package com.example.moja.pierwsza.aplikacja;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class View_Preference extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference);
}
}
Najważniejszą rzeczą do zapamiętania w tym elemencie jest powiązanie pliku
XML z naszą klasą. Nadal robimy to (najlepiej) w
OnCreate(), ale zamiast
setContentView używamy
addPreferencesFromResource.
Mamy więc obsługę ustawień,
czas na wyświetlanie zmian. Tworzymy kolejną klasę, tym razem będzie to normalne
Activity. U mnie plik ten nazywać się będzie
View_Preference_Activity. Użyłem również starego szablonu, bo i tak pobrane dane będziemy chcieli wyświetlić jako tekst, a do ustawień będziemy chcieli przejść przez tapnięcie elementu (tutaj przycisku). Pobieranie wartości z
SharedPreferences będzie się odbywać w onResume(), bo za każdym powrotem do
Activity chcemy widzieć aktualne dane (możemy również robić to w specjalnym listenerze nazwanym
onSharedPreferenceChanged)
. Nowa klasa prezentuje się tak
:
package com.example.moja.pierwsza.aplikacja;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
public class View_Preference_Activity extends Activity {
TextView textView;
SharedPreferences zapisane_ustawienia;
// Nasze pola w ustawieniach
Boolean CheckBox;
String EditText;
int List;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.view_listener_click);
final Button przycisk = (Button) findViewById(R.id.bt_click_listener);
final ImageView obrazek = (ImageView) findViewById(R.id.iV_click_listener);
textView = (TextView) findViewById(R.id.tv_click_listener);
// nasze ustawienia
zapisane_ustawienia = PreferenceManager.getDefaultSharedPreferences(this);
// ukrywamy obrazek, bo nie będzie nam potrzebny
obrazek.setVisibility(View.GONE);
przycisk.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Intent otworzopcje = new Intent(View_Preference_Activity.this, View_Preference.class);
startActivity(otworzopcje);
}
});
}
@Override
protected void onResume() {
super.onResume();
// zmienna checkbox = nasze ustawienia->pobierz warość true/false z klucza (+ domyślne ustawienie)
CheckBox = zapisane_ustawienia.getBoolean("pref_checkbox", false);
EditText = zapisane_ustawienia.getString("pref_edittext", "brak");
List = Integer.parseInt(zapisane_ustawienia.getString("pref_list", "0"));
// Tekst do wyświetlenia w textView
// \n to nowa linia
String ustawienia = "";
ustawienia += "Ustawienia to: \nCheckbox: ";
if (CheckBox) {
ustawienia += "true \n";
} else {
ustawienia += "false \n";
}
ustawienia += "EditText: " + EditText + " \n";
ustawienia += "Lista: " + List + " \n";
// Wyświetlamy wartości w textview
textView.setText(ustawienia);
}
}
Ustawienia aplikacji pobieramy z
SharedPreferences, do każdej opcji nawigujemy poprzez wybranie odpowiedniego typu i podanie klucza. Później wystarczy operować na pobranych danych.
To wszystko na dziś, sporo kodu, ale same ustawienia do trudnych nie należą. Dziękuję za uwagę i zapraszam do kolejnej części (wkrótce :))
