Android Settings Dialog Android – Kurs Stufe 2 (Orangegurt) Inhaltsverzeichnis 1 Settings Dialog .......................................................................................................................................... 2 2 Der Grundgedanke..................................................................................................................................... 2 3 Das erste Beispiel ...................................................................................................................................... 3 4 5 3.1 Das Layout der MainActivity ............................................................................................................ 3 3.2 Die Settings Activity ......................................................................................................................... 3 3.3 Das Settings Fragment ....................................................................................................................... 4 3.4 Das Preferences Layout ..................................................................................................................... 4 3.5 Der Code der MainActivity ............................................................................................................... 5 Das SharedPreferences Objekt .................................................................................................................. 6 4.1 Auslesen der Werte............................................................................................................................ 7 4.2 Ändern der Werte .............................................................................................................................. 7 4.3 Einfügen neuer Werte ........................................................................................................................ 7 4.4 Listener für geänderte Werte ............................................................................................................. 8 Die einzelnen Preference Elemente ........................................................................................................... 9 5.1 Grundeinstellungen............................................................................................................................ 9 5.2 Enable / Disable von Settings .......................................................................................................... 10 5.3 CheckBoxPreference ....................................................................................................................... 10 5.4 SwitchPreference ............................................................................................................................. 11 5.5 ListPreference .................................................................................................................................. 11 5.6 EditTextPreference .......................................................................................................................... 13 5.7 Submenü .......................................................................................................................................... 13 6 Lizenz ...................................................................................................................................................... 15 7 Haftung .................................................................................................................................................... 15 AnPr_Android_Course_2_3_Settings_v01.docx Seite 1 Android Settings Dialog 1 Settings Dialog Wir haben uns nun die wesentlichen Kenntnisse angeeignet, Android Apps zu designen. Wir können Elemente dem User präsentieren und Informationen wie Klicks und Text vom User abfragen. Wie ihr als Android Nutzer aber wisst, gibt es bei fast allen Apps die Möglichkeit, Einstellungen vorzunehmen – dies geschieht üblicherweise über die Settings. In diesem Dokument wollen wir uns die grundlegenden Eigenschaften des Settings Dialogs ansehen und wie wir auf die Einstellungswerte in den Activities zugreifen können. Bevor wir aber beginnen, noch ein kurzer Hinweis zum Thema API Version. Bei den Settings haben wir zwei Optionen – entweder wir gehen auf ein API Level < 11, dann müssen wir auf Methoden zurückgreifen, welche als deprecated geflagged wurden, oder man geht auf API Level >= 11, dann hat man die Möglichkeit auf neue Methoden zu gehen, welche nicht als deprecated eingestuft wurden. Im Wesentlichen hat man sich entschieden, die gesamte Struktur der Settings in Zukunft auf Fragments aufzubauen, und das bis dato übliche Verfahren, das Settings Designt direkt in einer Activity laufen zu lassen langsam aus den Apps herauszudrängen. Nach langem Überlegen habe ich mich nun dafür entschieden, mich auf die neue Technologie zu konzentrieren und die Version ab API Level 11 zu erklären, da die Anzahl der „alten“ Geräte langsam nicht mehr relevant ist. Leider muss man hier diese Entscheidung treffen, da die Support Library das Thema PreferenceFragment nicht berücksichtigt. Wer trotzdem sich die „old school“ Variante ansehen möchte, sei auf folgenden Link verwiesen: http://developer.android.com/guide/topics/ui/settings.html In diesem Dokument werden wir uns mit den grundlegendsten Techniken der Settings (oder auch „Preferences“) beschäftigen. Die weiterführenden Themen in diesem Zusammenhang werden wir auf einen späteren Zeitpunkt schieben, da wir sonst den Orangegurt überladen würden. Noch ein Hinweis zum Thema Design Guidelines. Android hat ein paar sinnvolle Anmerkungen zusammengefasst, wie man Setting Dialoge ansprechend designen soll. Diese findet ihr hier: http://developer.android.com/design/patterns/settings.html 2 Der Grundgedanke Der Dialog, in dem die Settings vorgenommen werden, ist erst mal nichts anderes, als eine Activity. Wir werden uns aufgrund der Oben genannten Gründe auf die Activity mit den Fragments konzentrieren – wir verwenden PreferenceFragment. Der Grund, warum wir nicht einfach normale Fragments verwenden können liegt in der Tatsache, dass die Preferences in einem gesonderten File abgelegt werden, welches von überall unserer App gelesen werden kann. Hinzu kommt, dass dieses File beim Neustart unserer App neu gelesen wird und somit die alten Einstellungen wieder hergestellt werden. Wir müssen also unsere Einstellungen nicht jedes Mal auf’s Neue eingeben. Wie das File heißt und wo es liegt ist für uns als Entwickler erst mal nicht wichtig – Android wird sich um alles kümmern. Da das Design für die Preferences immer einheitlich ist, wurde das File in dem die gewünschten Settingswerte enthalten sind und das File, welches für das Layout zuständig ist, zusammengefasst in ein einziges XML File. Wir werden uns in diesem Dokument im Wesentlichen die Möglichkeiten ansehen, welche verschiedenen Einstellungen wir in diesem File machen können. Auch der Zugriff auf die Settings sollte bei allen Apps einigermaßen einheitlich sein. Üblicherweise wird über das „OptionsMenu“ der Dialog zum Einstellen der Settings aufgerufen. Auch dieses Thema werden wir hier behandeln – wenngleich wir das OptionsMenu erst mal nur für die Settings betrachten und nicht für die weiteren Möglichkeiten. Auch das werden wir auf später verschieben. Seite 2 Android Settings Dialog 3 Das erste Beispiel Wir werden nun eine kleine App schreiben, bei der wir einen Settings Dialog realisieren. Vorerst werden wir die Funktionalität recht schmal halten. Wir werden in der MainActivity lediglich ein TextView Element haben, welches anzeigt, ob in den Settings unsere einzige vorhandene Checkbox selektiert ist, oder nicht. 3.1 Das Layout der MainActivity Wir sind inzwischen ja geübt, neue Projekte zu erzeugen. Wir schaffen ein Projekt namens „SettingsTest“ und fügen dort eine MainActivity ein. Diese beinhaltet lediglich eine TextView. Hier das Layout unserer MainActivity (activity_main.xml): <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <TextView android:id="@+id/settingsTestText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="@string/empty_value" /> </RelativeLayout> Wie ihr seht ist das nichts Weltbewegendes. Wir haben dem TextView auch nur einen Leerstring zugewiesen (der natürlich in strings.xml auch eingetragen werden muss),da wir den Inhalt unseres TextViews aus den Settings übernehmen müssen. 3.2 Die Settings Activity Wie wir Oben beschrieben haben, werden wir unsere Settings in einer eigenen Activity einbetten, welche das PreferenceFragment beherbergt. Um diese Activity zu erzeugen, müssen wir eine neue Klasse erstellen und sie von der Acitivty Klasse ableiten. Hierbei rufen wir in der onCreate Methode onCreate der Superklasse auf und instanziieren unser Fragment MySettingsFragment als zentraler Inhalt (android.R.id.content – das ist eine StandardID für den Inhalt). Das Ganze passiert wie bei Fragments üblich über den FragmentManager (wir erinnern uns – wenn wir ab API Level 11 Fragments umsetzen, brauchen wir den getFragmentManager und nicht den getSupportFragmentManager): public class MySettingsActivity extends Activity { @Override Seite 3 Android Settings Dialog protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getFragmentManager().beginTransaction().replace( android.R.id.content, new MySettingsFragment()).commit(); } } Wichtig ist nun noch, dass wir die neue Activity Klasse im Manifest File AnroidManifest.xml registrieren, indem wir im Tag <application> am Ende folgende Konfiguration einfügen: <activity android:name="com.example.settingstest.MySettingsActivity" android:label="@string/title_mysettingsactivity_main" > </activity> Eclipse wird nun monieren, dass die Klasse MySettingsFragment noch nicht existiert – diese werden wir nun nachreichen. 3.3 Das Settings Fragment Der eigentliche Inhalt der Activity wird über ein Fragment dargestellt. Die Besonderheit hier ist, dass wir hier kein „normales“ Fragment verwenden, sondern ein PreferenceFragment. Dieses benötigt kein übliches Layout als Parameter, sondern ein preferneces Layout, welches wir uns im nächsten Kapitel näher ansehen werden. Dort werden wir für unsere Checkbox in dem Preferences Dialog noch einen Namen (eigentlich „Key“) festlegen – er soll „pref_test“ heißen. Um im Programm später darauf zugreifen zu können definieren wir hier eine Konstante, welche diesen Namen beinhaltet. public class MySettingsFragment extends PreferenceFragment { public static final String KEY_PREF_TEST = "pref_test"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); } } 3.4 Das Preferences Layout Üblicherweise wird das Layout unseres PreferencesFragment in einem XML File abgelegt, welches sich im Ordner res/xml befindet und preferences.xml heißt. Wir legen also einen neuen Unterordner unter „res“ an und nennen diesen „xml“. Hier tragen wir ein leeres XML File ein, welches wir wie folgt editieren: <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/ android"> <CheckBoxPreference android:key="pref_test" android:title="@string/pref_test_title" android:summary="@string/pref_test_summ" android:defaultValue="true" /> </PreferenceScreen> Seite 4 Android Settings Dialog Wir tragen also eine Checkbox ein, welche auf den Key „pref_test“ hört. Weiterhin geben wir der Checkbox noch einen Titel – das wird der groß geschriebene Text im Settings Dialog sein und eine Summary, was der kleinere Text sein wird. Der Titel bei uns soll „My Settings“ sein und die Summary „Do your Settings“. Diese Strings müsst ihr natürlich noch in strings.xml eintragen. 3.5 Der Code der MainActivity In der MainActivity lassen wir nun alle Fäden zusammenlaufen. Die onCreate Methode habe ich nicht weiter angepasst – das was Eclipse mir eingetragen hat ist OK. Die folgende Methode lassen wir zwar auch unangetastet, ich möchte sie aber an dieser Stelle mal kurz vorstellen. Die onCreateOptionsMenu ist die Methode, welche das Standardmenü erscheinen lässt. Diese Funktion wird bei vielen Android Geräten über die Taste links unten, bzw. wenn keine eigene Taste existiert im Bildschirm unterhalb des ActionMenü rechts oben gestartet. In diesem Standardmenü befindet sich im Regelfall der „Settings“ Eintrag. Wenn diese Methode also existiert, dann können wir mit dem MenuInflater das Standardmenü auf unseren Bildschirm zaubern. @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } Das Layout unseres Menüs finden wir unter res/menu im File activity_main.xml: <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/menu_settings" android:orderInCategory="100" android:showAsAction="never" android:title="@string/menu_settings"/> </menu> Die einzelnen Bedeutungen der Einträge werden wir uns zu einem späteren Zeitpunkt ansehen, wichtig an dieser Stelle ist nur, dass wir hier ein Menü erzeugen, welches über den Menübutton zustande kommt. Man kann hier noch einen icon (also eine Grafik) reinhängen. Das ganze Thema „Menü“ werde ich in die nächste Gürtelfarbe reinpacken, da wir hier wieder ein paar Dinge bezüglich API Level 11 beachten müssen und das den Orangegurt sprengen würde. Wer vorher sich schon schlau machen will, sei auf diese Links verwiesen: http://developer.android.com/guide/topics/resources/menu-resource.html http://developer.android.com/guide/topics/ui/actionbar.html Jetzt haben wir zwar das (zugegebenermaßen sehr einfache) Layout festgelegt. Nun müssen wir nur noch dafür sorgen, dass das Menü auch angezeigt wird. Das erledigen wir über die Methode „onOptionsItemSelected“: @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_settings: startSettings(); return true; default: return super.onOptionsItemSelected(item); } } Da wir dem Settings Menüeintrag eine ID gegeben haben, können wir identifzieren, über welchen Eintrag die Methode aufgerufen wurde. Üblicherweise packen wir die ganze Funktionalität in eine Switch/Case AnSeite 5 Android Settings Dialog weisung hinein, damit wir diesen Teil einfach erweitern können. Um das Settings Menü zu starten, habe ich eine eigene Methode spendiert. Hier starte ich – wie sollte es anders sein – den Settings Dialog mit Hilfe eines Intents: private void startSettings() { Intent intent = new Intent(); intent.setClass(MainActivity.this, MySettingsActivity.class); startActivity(intent); } Nun kommen wir zu der Methode, welche die Settingsinformationen auslesen und in die TextView einbauen soll. Da das Settings Menü unsere MainActivity in den Pausenstatus versetzen wird, können wir davon ausgehen, dass wenn wir aus den Settings wieder rauskommen, die Methode onResume aufgerufen wird. Dies ist also die ideale Stelle, die Settings auszulesen: @Override protected void onResume() { super.onResume(); SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); boolean prefTestChecked = sharedPref.getBoolean(MySettingsFragment.KEY_PREF_TEST, false); TextView myTextView = (TextView) findViewById(R.id.settingsTestText); myTextView.setText(String.valueOf(prefTestChecked)); } Wir rufen (natürlich) wieder die Methode der Superklasse auf, um die internen Vorgänge zu erlauben. Anschließen holen wir uns die SharedPreferences. Dies ist ein wichtiges Objekt, da es uns ermöglicht die Preferences zu speichern und wieder zu laden. Ich gehe im nächsten Kapitel nochmal kurz auf dieses Objekt ein. Danach hole ich mir die Information, ob die Checkbox in unserem Settings Dialog ausgewählt (checked) ist, oder nicht: SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); boolean prefTestChecked = sharedPref.getBoolean(MySettingsFragment.KEY_PREF_TEST, false); Der erste Parameter ist der Key-Wert unseres Settings. Sollten die Settings nicht gefunden worden sein, legen wir noch einen Defaultwert im zweiten Parameter fest – ich habe mich hier für „false“ entschieden. Die Information packe ich in eine Boolean Variable, welche ich im Anschluss lediglich in einen String konvertiere und in die TextView hineinschreibe. So, das war es auch schon. Nun können wir die App starten und das Menü aufrufen – den Settings Dialog starten und die Checkbox auswählen. Wenn wir die Back Taste drücken sehen wir, dass das „false“ sich nun zu einem „true“ geändert hat. Wenn wir den Vorgang wiederholen und die Checkbox deselektieren, sehen wir wieder ein „false“. Interessant ist auch, dass wenn wir die App schließen und danach wieder neu starten, der Wert aus dem letzten Lauf der App wiedergefunden wird. Android hat es sich also gemerkt, was wir beim letzten Mal eingestellt haben – wir müssen uns also nicht mühsam um irgendwelches Persistieren kümmern! 4 Das SharedPreferences Objekt Wie schon erwähnt, dient das SharedPreferences Objekt dazu, die Statuswerte zu speichern bzw. wieder zu laden. Dabei ist dieses Objekt sehr eng mit unserem PreferenceFragment verknüpft, so dass wir uns nicht um die Details der Persistierung kümmern müssen. Einstellungen im PreferenceFragment werden automatisch in unserem SharedPreferences Objekt und danach im Filesystem abgelegt. Dies kann man zwar mit dem Eintrag PreferenceScreen „android:persistent="false"“ unterbinden, wobei sich dies nicht empfiehlt. Seite 6 Android Settings Dialog 4.1 Auslesen der Werte Weiterhin ist das SharedPreferences Objekt von jeder Stelle unserer App aufrufbar, da wir es von allen Activities mit Hilfe des PreferenceManager aufrufen können. Ein Aufruf (aus dem vorausgegangenen Kapitel) sieht wie folgt aus: SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); boolean prefTestChecked = sharedPref.getBoolean(MySettingsFragment.KEY_PREF_TEST, false); Wichtig ist, dass ihr die einzelnen Keys sauber pflegt und euch eine sinnvolle Namenskonvention überlegt, damit ihr später nicht durcheinander kommt. 4.2 Ändern der Werte Die Werte werden natürlich mit dem Settings Dialog geändert. Es gibt aber auch Möglichkeiten, die Settings programmatisch zu ändern. Da – wie bei den Views auch – alle XML basierten Elemente in Java Klassen münden, gibt es auch für die einzelnen Preferences Elemente Java Entsprechungen. Wenn wir also unsere Checkbox programmatisch auf „true“ setzen wollen, dann müssen wir lediglich das zugehörige Java Objekt finden und dies auf den gewünschten Wert setzen: CheckBoxPreference checkBoxPrefTest = (CheckBoxPreference) this.findPreference(MySettingsFragment.KEY_PREF_TEST); if (checkBoxPrefTest!= null) { checkBoxPrefTest.setChecked(true); } Wir holen also einfach die Preferences und suchen dort den Preferencewert mit dem gegebenen Key. Wichtig ist, dass die Preferences nur im PreferenceFragment gefunden werden können. Wenn wir von der Activity aus die Settings ändern wollen, können wir mit einem Interface arbeiten, wie wir es bei den „normalen“ Fragments ja bereits gesehen haben. 4.3 Einfügen neuer Werte In dem SharedPreferences Objekt können auch andere Werte abgelegt werden, welche nicht im Settings Dialog eingestellt werden. Dies kann sinnvoll sein, wenn interne Programmstatuswerte nicht verloren gehen dürfen. Hierfür benötigen wir einen Editor für die Preferences. Wir ergänzen unsere Activity wie folgt: @Override public void onDestroy() { super.onDestroy(); SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor myEditor = sharedPref.edit(); myEditor.putString(KEY_PREF_DYN, "my dynamic value"); myEditor.commit(); } Wir erzeugen uns einen Editor, indem wir mit der edit() Methode diesen Editor einer Variablen zuweisen. Dies startet auch automatisch eine Transaktion, welche wir am Ende mit „commit()“ abschließen müssen. Mit Hilfe dieses Editors können wir nun einen neuen Wert eintragen. Ich habe mich für einen Stringwert entschieden, der einen eindeutigen Key-Wert benötigt, den wir in der Activity Klasse festlegen müssen: public static final String KEY_PREF_DYN = "pref_dynamic"; In der onResume Methode ergänzen wir unseren Code nun wie folgt – wir lesen nach dem Checkbox Wert auch unseren neuen dynamischen Wert ein und schreiben anschließend nicht nur den boolschen Wert in unser Textfeld, sondern auch noch unseren dynamischen Settingswert: Seite 7 Android Settings Dialog String prefDynValue = sharedPref.getString(KEY_PREF_DYN, "empty"); myTextView.setText(String.valueOf(prefTestChecked) + " " + prefDynValue); Wie ihr sehen werdet, wird unser TextView Element beim nächsten Starten unserer App den Text „false empty“ anzeigen (sofern die Checkbox zuletzt deselektiert war), da wir den dynamischen Settingswert noch nicht eingetragen haben und somit der Defaultwert greift. Wenn wir allerdings die App beenden, wird onDestroy aufgerufen und der dynamische Wert in die Settings eingetragen. Beim nächsten App Start wird nun der Wert gefunden und das TextView Element wird anzeigen „false my dynamic value“. Wir können folgende einfache Datentypen in unser SharedPreferences Objekt eintragen: Datentyp: boolean float int long String Set<String> Methode: putBoolean(key, value); putFloat(key, value); putInt(key, value); putLong(key, value); putString(key, value); putStringSet(key, value); Set ist eine Sammlung von Strings, welche wie folgt instanziiert wird: Set<String> set = new HashSet<String>(); Im set können nun mit “add” Werte eingetragen werden, welche wir als entsprechende Liste im SharedPreferences Objekt speichern und wieder herauslesen können. Beim Lesen können wir aus dem HashSet ein Array erzeugen. 4.4 Listener für geänderte Werte Der letzte Punkt für unser SharedPreference Objekt ist der OnSharedPreferenceChangeListener. Dieser wird aktiv, wenn ein Setting geändert wurde. Folgende Funktionalität soll dies verdeutlichen – wenn unsere Checkbox selektiert ist, soll ein anderer Summarytext angezeigt werden, als wenn sie nicht selektiert ist. Wir definieren zuerst unsere Strings im strings.xml: <string name="pref_test_summ">Check for displaying true</string> <string name="pref_test_summ_checked"> Uncheck for displaying false</string> Danach implementieren wir den Listener in unser MySettingsFragment: public class MySettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(KEY_PREF_TEST)) { setSummaryText( (CheckBoxPreference)findPreference(KEY_PREF_TEST)); } } Die Methode “onSharedPreferenceChanged” wird wie immer von Eclipse per Mausklick implementiert. Wir ergänzen lediglich den Code, der für den Tausch des SummaryTexts zuständig ist. Diesen habe ich in eine eigene Methode eingefügt, welche sich um die Anzeige des richtigen Texts kümmert. Damit wir auch beim Seite 8 Android Settings Dialog erstmaligen Aufruf des Settings Dialogs den richtigen Text zu sehen bekommen, rufen wir diese Methode auch beim onCreate auf: @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); setSummaryText((CheckBoxPreference)findPreference(KEY_PREF_TEST)); } Die Methode ist relativ einfach gestrickt und sollte uns keine Probleme bereiten: private void setSummaryText(CheckBoxPreference myCheckBox) { if (myCheckBox != null) { if (myCheckBox.isChecked()){ myCheckBox.setSummary(R.string.pref_test_summ_checked); } else { myCheckBox.setSummary(R.string.pref_test_summ); } } } Es wird zuerst geprüft, ob der Aufrufer das Preference Element auch wirklich gefunden hat. Anschließend wird geprüft, ob die Checkbox selektiert ist und demensprechend wird der richtige String als Summary eingesetzt. Was nun noch fehlt ist, den Listener zu registrieren. Da wir diesen Listener wirklich nur dann brauchen, wenn wir aktiv mit dem Settings Dialog arbeiten, registrieren wir ihn in der onResume Methode und entfernen ihn wieder in der onPause Methode: @Override public void onResume() { super.onResume(); getPreferenceScreen().getSharedPreferences(). registerOnSharedPreferenceChangeListener(this); } @Override public void onPause() { super.onPause(); getPreferenceScreen().getSharedPreferences(). unregisterOnSharedPreferenceChangeListener(this); } 5 Die einzelnen Preference Elemente Nun haben wir die wichtigsten Elemente kennengelernt, um die Settings in unser Programm einzubauen, wobei wir als Beispiel eine Checkbox verwendet haben. Wir wollen uns in den nächsten Kapiteln eine Auswahl an möglichen anderen Settings Elementen ansehen und die wichtigsten Einstellungen. 5.1 Grundeinstellungen Zuerst kommt natürlich der „key“ Eintrag, ohne den wir keinen eindeutigen Zugriff auf unsere Preferences haben. Es empfiehlt sich auch für jeden Settings Eintrag einen Default Value zu setzen, was im Prinzip der Anfangszustand ist. Weiterhin kennt jedes Element zumindest die beiden Werte Title und Summary. Title ist die im großen Text geschriebene Überschrift und die Summary die etwas kleiner geschriebene Zusammenfassung unterhalb der Überschrift. Seite 9 Android Settings Dialog Den Code dazu haben wir weiter Oben schon kennengelernt – der Vollständigkeit halber hier nochmal die XML Definition im preferences.xml File: <CheckBoxPreference android:key="pref_test" android:title="@string/pref_test_title" android:summary="@string/pref_test_summ" android:defaultValue="true" /> Zusätzlich ist es manchmal noch sinnvoll eine Grafik mit einzubinden. Dies erfolgt über das icon Attribut: android:icon="@drawable/ic_launcher" Der Einfachheit halber habe ich hier das Drawable ic_launcher genommen, da es standardmäßig von Eclipse bereits eingefügt wurde. 5.2 Enable / Disable von Settings Settingelemente können aktiviert und deaktiviert sein. Dies kann man mit zweierlei Methoden ermöglichen. Zuerst die einfachere – die Abhängigkeiten. Es gibt gewisse Settings, welche nur dann sinnvoll gesetzt werden können, wen ein anderes Setting auf „true“ steht. Zur Verdeutlichung ergänzen wir unser preferences.xml File wie folgt: <CheckBoxPreference android:key="pref_test" android:title="@string/pref_test_title" android:summary="@string/pref_test_summ" android:defaultValue="true" android:icon="@drawable/ic_launcher"/> <CheckBoxPreference android:key="pref_test2" android:title="@string/pref_test_title" android:summary="@string/pref_test_summ" android:defaultValue="true" android:dependency="pref_test"/> Wichtig ist hier der Eintrag „android:dependency="pref_test"“. Wir geben hier an, dass es eine Abhängigkeit zwischen dem pref_test2 und dem pref_test gibt und zwar wird dies dergestalt interpretiert, dass pref_test2 nur dann aktiv ist, wenn pref_test ausgewählt ist. Sobalt pref_test keinen Haken mehr hat, ist pref_test2 inaktiv. Eine zweite Möglichkeit ist es, die Elemente programmatisch zu aktivieren, bzw. deaktivieren. Wie wir eine Referenz auf die Checkbox bekommen haben wir in den Oberen Kapiteln gesehen. Deaktivieren können wir das Element wie folgt: myCheckBox.setEnabled(false); Wenn wir den Status auf „Aktiv“ setzen wollen, dann müssen wir als Parameter lediglich „true“ setzen. Wir können auch programmatisch feststellen, ob das Element aktiv ist: myCheckBox.isEnabled() 5.3 CheckBoxPreference Wie wir in den oberen Beispielen schon gesehen haben, ist die CheckBoxPreference recht einfach umsetzbar. Den XML Code werde ich an dieser Stelle nicht nochmal wiederholen, einfach im vorausgehenden Kapitel nochmal reinschauen. Die wichtigsten Java Methoden haben wir auch schon gesehen. Hier möchte ich jedoch die zwei wichtigsten kurz ansprechen: Seite 10 Android Settings Dialog Methode: .isChecked() .setChecked(value) Beschreibung: Liefert „true“ zurück, wenn die Checkbox selektiert ist, sonst „false“ Wenn value auf „true“ steht, wird die Checkbox selektiert, wenn value auf „false“ steht, wird sie deselektiert. Alle weiteren Methoden können unter folgenden Links ersehen werden: http://developer.android.com/reference/android/preference/Preference.html http://developer.android.com/reference/android/preference/TwoStatePreference.html http://developer.android.com/reference/android/preference/CheckBoxPreference.html 5.4 SwitchPreference Die SwitchPreference ist prinzipiell nichts anderes als eine Checkbox, nur dass sie optisch anders dargestellt ist. In den Java Klassen kann man dies daran erkennen, dass beide eine Ableitung der Klasse „TwoStatePreference“ sind. Der Code sieht entsprechend einfach aus: <SwitchPreference android:key="pref_test3" android:title="@string/pref_test_title" android:summary="@string/pref_test_summ" android:switchTextOn="@string/pref_switch_text_on" android:switchTextOff="@string/pref_switch_text_off" android:defaultValue="true" /> Die beiden Elemente switchTextOn und switchTextOff sind optional. Wenn sie nicht vorhanden sind, wird der Text des Schiebers On und Off sein. Mit diesen beiden Elementen können wir den Text sprachlich individualisieren. Die Methoden der Java Klasse sind identisch mit denen der Checkbox: Methode: .isChecked() .setChecked(value) Beschreibung: Liefert „true“ zurück, wenn die Checkbox selektiert ist, sonst „false“ Wenn value auf „true“ steht, wird die Checkbox selektiert, wenn value auf „false“ steht, wird sie deselektiert. Auch hier findet ihr die notwendigen zusätzlichen Infos im Netz: Alle weiteren Methoden können unter folgenden Links ersehen werden: http://developer.android.com/reference/android/preference/Preference.html http://developer.android.com/reference/android/preference/TwoStatePreference.html http://developer.android.com/reference/android/preference/SwitchPreference.html Wer es ganz indiviuell haben möchte, kann sich die View, welche mit dem Switch verbunden ist auch individuell zusammenbauen und über das Attribut android:layout auch laden. Da dies hier aber zu weit führen würde, muss ich an dieser Stelle lediglich auf die API verweisen. 5.5 ListPreference Ein auch recht häufig anzutreffendes Element bei den Settings ist die „ListPreference“. Dies ist im Wesentlichen ein Feld von Radio Buttons. Dieses öffnet sich als Subdialog und listet alle vorher definierten Werte auf. Diese müssen aber zuvor definiert werden. Dies geschieht in einem String Array, welche auch in einem Array festgelegt werden können. Hierzu erzeugen wir im Ordner res/values das File array.xml und schreiben folgendes rein: <?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="pref_list_example_disp"> <item>Wert A</item> <item>Wert B</item> Seite 11 Android Settings Dialog <item>Wert C</item> </string-array> <string-array name="pref_list_example_values"> <item>0</item> <item>1</item> <item>2</item> </string-array> </resources> Wir haben somit zwei verschiedene String Arrays geschaffen. Das erste ist für die Anzeige der Werte im Dialog (wenn wir mehrsprachig arbeiten, so muss dieser Bereich entsprechend in die sprachspezifischen Unterordner – wir erinnern uns an den Gelbgurt). Das zweite Array steht für die Werte, welche beim Auswählen hinterlegt werden. Dies muss für eine saubere Sprachunabhängigkeit gewährleistet sein! Weiterhin müssen wir nun unser strings.xml File mit folgenden Werten ergänzen: <string name="pref_list_default">2</string> <string name="pref_list_title">Select values</string> <string name="pref_list_summ">Click for opening the dialog</string> Hier finden wir die Werte für unseren Titel und der Summary. Was wir hier auch hinterlegen ist der Defaultwert, welcher nicht der Anzeigewert, sondern der hinterlegte, sprachunabhängige Wert sein muss. In unserem preferences.xml File fügen wir das Element nun ein;: <ListPreference android:key="pref_list_example" android:title="@string/pref_list_title" android:summary="@string/pref_list_summ" android:entries="@array/pref_list_example_disp" android:entryValues="@array/pref_list_example_values" android:defaultValue="@string/pref_list_default"/> Wie wir sehen, fügen wir neben den üblichen Attributen nun die Einträge als Referenzen auf unsere neu erzeugten Arrays ein – dies gilt für unser Anzeigewerte (android:entries), als auch für unsere hinterlegten Werte (android:entryValues). Der sich öffnende Dialog kann noch weiter konfiguriert werden, wobei ich an dieser Stelle hierauf nicht weiter eingehen möchte. Hier noch die wichtigsten Methoden: Methode: .getEntryValues() Beschreibung: Liefert ein Array von CharSequence Werten, welche die Werte des entryValues Array beinhaltet. .findIndexOfValue(value) Gibt die Indexposition des gegebenen Wertes (entsprechend des Arrays aus getEntryValues). .getValue() Gibt den Wert aus, der gerade ausgewählt ist. .setValue(value) Setzt den Wert, der gerade ausgewählt ist auf „value“, wobei dieser Teil des Arrays aus getEntryValues sein muss. Alle weiteren Infos, wie immer im Netz: http://developer.android.com/reference/android/preference/Preference.html http://developer.android.com/reference/android/preference/ListPreference.html Seite 12 Android Settings Dialog 5.6 EditTextPreference Das letzte Element in dieser Reihe welches ich besprechen möchte ist das EditTextPreference Element. Es ist zwar relativ selten, dass man wirklich Texteingaben machen möchte, aber hin und wieder kommt man hier nicht drum rum. Prinzipiell ist das EditTextPreference Feld genauso zu nutzen wie eine Kombination eines EditText Views und einer normalen Preference View. Um dies zu verdeutlichen setzen wir mal ein EditTextPreference um, welches nur Ziffern akzeptiert. Zuerst erweitern wir die strings.xml: <string name="pref_text_default">15</string> <string name="pref_text_title">Enter number</string> <string name="pref_text_summ">Click for opening the dialog</string> Danach fügen wir in preferences.xml folgenden Eintrag ein: <EditTextPreference android:key="pref_edittext_test" android:title="@string/pref_text_title" android:summary="@string/pref_text_summ" android:defaultValue="@string/pref_text_default" android:inputType="number"/> Wie wir sehen, können wir auch hier einen inputType vorgeben. Die Javamethoden sind ebenfalls keine Überraschung. Methode: .getText() .setText(value) Beschreibung: Liefert den eingegebenen Text zurück. Belegt den eingegebenen Text neu mit dem Wert „value“. Weitere Details findet ihr unter. http://developer.android.com/reference/android/preference/Preference.html http://developer.android.com/reference/android/preference/DialogPreference.html http://developer.android.com/reference/android/preference/EditTextPreference.html 5.7 Submenü Wenn zu viele Settings in einem Dialog vorgesehen sind empfiehlt es sich, diesen aufzuteilen. Die einfachste Möglichkeit bietet das Einsetzen eines weiteren PreferenceScreens. Dieser wird lediglich in den bereits existierenden PreferenceScreen eingebettet: <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <CheckBoxPreference android:key="pref_test" android:title="@string/pref_test_title" android:summary="@string/pref_test_summ" android:defaultValue="true"/> <PreferenceScreen android:key="pref_subscreen" android:title="@string/pref_sub_title" android:summary="@string/pref_sub_summ"> <SwitchPreference android:key="pref_test3" android:title="@string/pref_test_title" android:summary="@string/pref_test_summ"/> </PreferenceScreen> </PreferenceScreen> Seite 13 Android Settings Dialog Wie ihr seht, bekommt der innere PreferenceScreen auch einen Titel und eine Summary. Ansonsten wird der innere PreferencesScreen genauso gehandhabt, wie der äußere – es können beliebige Elemente eingefügt werden. Wenn ihr die App startet, dann werdet ihr die altbekannte Checkbox sehen und einen weiteren Eintrag. Wenn ihr auf diesen Klickt, dann öffnet sich der Subscreen und ihr seht dort die inneren Elemente (in unserem Fall „nur“ das SwitchPreferences Element. Seite 14 Android Settings Dialog 6 Lizenz Diese(s) Werk bzw. Inhalt von Maik Aicher (www.codeconcert.de) steht unter einer Creative Commons Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 3.0 Unported Lizenz. The Android robot is reproduced or modified from work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License. “Eclipse” and the Eclipse Logo are trademarks of Eclipse Foundation, Inc. "Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners." 7 Haftung Ich übernehme keinerlei Haftung für die Richtigkeit der hier gemachten Angaben. Sollten Fehler in dem Dokument enthalten sein, würde ich mich über eine kurze Info unter [email protected] freuen. Seite 15