• Save
Flexibles UI-Design
Upcoming SlideShare
Loading in...5
×
 

Flexibles UI-Design

on

  • 1,265 views

 

Statistics

Views

Total Views
1,265
Views on SlideShare
1,201
Embed Views
64

Actions

Likes
0
Downloads
0
Comments
0

2 Embeds 64

http://www.openknowledge.de 63
http://us-w1.rockmelt.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Flexibles UI-Design Flexibles UI-Design Presentation Transcript

  • Ausgabe 1/2012 EXKLUSIV FÜR ABONNENTEN: DAS GROSSE ANDROID-POSTER! android 360 www.android360.de Deutschland € 9,80 Österreich € 11,70 Schweiz sFr 17,50 Luxemburg € 11,90 Mobile Development, Marketing, Business magazin Modulare Android-Anwendungen | App-Store-Optimierung | Enterprise-Integration | ActionBar | Fragments Das LEGO Android-Apps: Modulare Prinzip Zeit und Geld sparen! ge Jede Mern tests N EU: Hardwa e App-Store-Optimierung Tipps und Tricks für mehr Downloads Android Enterprise Integration Mit dem Androiden ins Büro Frei-Haus-Lieferung des Print-Magazins! Das ActionBar-Pattern Alle Ausgaben online Auf dem Weg zur einheitlichen Navigation immer und überall verfügbar! Flexibles UI-Design Offline-PDF-Export Android-UI-Fragmentego: mobiletechmag.de/abocall: +49(0)6123 92 38 -239 (Mo–Fr, 8 –17 Uhr)
  • USER INTERFACES | UI-FRAGMENTE Android-UI-FragmentePOSTERThema Flexibles UI-Design Das Android SDK ist vom visuellen Konzept her so ausgerichtet, dass Softwareentwickler ihre mobilen Anwendungen für verschiedenste Bildschirmgrößen und -auflösungen auf Basis derselben Sourcen umsetzen können. So weit, so gut. Doch was ist, wenn völlig unterschiedliche Device-Typen wie Smart- phones, Tablet-PCs oder TVs und deren spezifische Eigenschaften unterstützt werden sollen? Auch hier gibt es seit Android 3.0 beziehungsweise 4.0 eine Lösung: UI-Fragmente. von Lars Röwekamp ger als eine Activity. Die Grundidee der Fragmente ist, dass man je nach Capabilities des Ziel-Device eines oder Dass ein Betriebssystem wie Android mittelfristig nur mehrere von ihnen innerhalb einer Activity einbinden dann Erfolg haben wird, wenn es der zu erwartenden und so dynamisch eine Multi-Pane UI aufbauen kann. Fragmentierung am Markt Herr werden kann, war Während man zum Beispiel für einen klassischen Mas- von Anfang an allen klar. Entsprechend früh flossen ter Detail Use Case auf einem Tablet-PC links eine Lis- Konzepte wie Layout-Manager und Multi-Screen- te von Elementen, Fragment A, und rechts die Details Konfiguration – zur Berücksichtigung unterschiedlicher des gerade selektierten Elements, Fragment B, anzeigen Bildschirmgrößen und -auflösungen – in das Android kann, würde man dies auf einem Smartphone auf zwei SDK ein und gehören mittlerweile zum kleinen Einmal- verschiedene Screens verteilen (Abb. 1). eins eines jeden Android-Entwicklers. Problematischer Im Grunde genommen kann man sich ein Fragment wird es allerdings, wenn die bestmögliche User Experi- also wie eine Art Mini- oder Sub-Activity vorstellen. ence nicht nur von einer an den Bildschirm angepassten Es besitzt zwar einen eigenen Lifecycle und ein eigenes Ressource oder einem optimal skalierten Bild abhängt. Event Handling, benötigt aber immer eine umliegende Spätestens seit der Einführung von Android-basierten Activity, in dessen Lifecycle es sich integriert. Pausiert Tablet-PCs und TVs schreit die bisherige Designphilo- eine Activity, pausieren auch alle enthaltenen Fragmente. sophie „one design fits all“ nach einer Überarbeitung. Wird eine Activity zerstört, werden auch alle zugehöri- Diese existiert seit der Version 3.0 für Tablet-PCs und gen Fragmente zerstört. Abbildung 2 zeigt den Lifecycle seit 4.0 nun auch für alle anderen Android Devices in des Fragments in Abhängigkeit vom Activity State. Form von UI-Fragmenten. Wo bleibt der Use Case? Weniger ist mehr Ein Fragment wird zwar grundsätzlich eingebettet in Was genau muss man sich unter einem Fragment vor- eine Activity verwendet, kann aber durchaus in verschie- stellen? Ein Fragment ist laut Android-SDK-Dokumen- denen Activities wiederverwendet werden. Ebenfalls ist tation eine Art Activity-Modul mit (optional) eigener es möglich, Fragmente zur Laufzeit zu manipulieren, sie UI und eigenem Lifecycle. Es ist somit mehr als eine also zu einer Activity hinzuzufügen oder aus dieser zu klassische UI-Komponente wie der Button und weni- entfernen, um so zur Laufzeit dynamisch eine geräte- spezifische Multi-Pane UI aufzubauen. Im Rahmen einer solchen Fragment-Transaktion lassen sich die Fragmen- te auch auf einen Back Stack legen, wo sie von der Acti- vity verwaltet und vom Anwender mittels Back-Button wieder hervorgeholt werden können. Das Konzept der Fragmente wurde bewusst stark an die bereits bekann- ten Activities angelehnt, erweitert diese aber gleich um eine ganze Reihe von Features, um so ein flexibles UI- Design zu ermöglichen: • Fragmente sind per Definition als embeddable UI- Komponenten konzipiert und haben entsprechende Schnittstellen zur Kommunikation der umliegenden Abb. 1: Möglichkeiten zur Einbindung der Fragmente A und B je nach Ziel-Device Activity.80 android 360 1 | 2012 www.android360.de
  • UI-FRAGMENTE | USER INTERFACES• Fragmente binden sich optimal in den Lifecycle der hilfe des im ListFragment umgebenden Activity ein und ergänzen diesen durch automatisch zur Verfügung ihren eigenen Lifecycle. stehenden ListAdapter dar-• Der State eines Fragments wird automatisch vom gestellt. Die AsyncTask ist Framework gemeinsam mit dem State der umliegen- dabei notwendig, um den den Activity verwaltet. UI Thread während des• Ein spezielles DialogFragment erlaubt die Darstel- Parsing-Vorgangs nicht un- lung eines Dialogs, der von der umliegenden Activity nötig zu blockieren. Soweit gesteuert werden kann. zur initialen Anzeige der• Ein spezielles ListFragment ermöglicht die einfache RSS-Feed-Übersicht. Aber Umsetzung von Master-Detail-Beziehungen. wie findet nun die Verbin- dung zur Detailansicht desTipp: Bei der Konzeption eines Fragments sollte man ausgewählten Feed-Ele-immer die potenzielle Wiederverwendung im Hinter- ments statt und woher weißkopf behalten und einen entsprechend modularen Auf- die Anwendung, ob dasbau planen. für die Anzeige zuständige Fragment, RSSDetailFrag-Genug der Theorie! ment, in derselben ActivityNachdem wir uns ein wenig mit den theoretischen (Landscape) oder in einerGrundlagen auseinandergesetzt haben, wollen wir uns eigenen (Portrait) darge-das Konzept der Fragmente zusätzlich an einem kleinen stellt werden soll?Beispiel verdeutlichen. Als Basis für das Beispiel soll eineAnwendung dienen, die in Anlehnung an [1] und [2] den Qual der Wahl – Teil Iaktuellen JAXenter RSS Feed ausliest und darstellt. Je Beginnen wir mit der Be-nach Orientierung des Devices werden die RSS-Feed- antwortung der zweiten Abb. 2: Fragment-LifecycleÜbersicht und die Details des aktuell selektierten Feed- Frage. Etwas anders formu-Elements entweder auf einem Screen – Landscape – oder liert könnte man auch fragen: „Woher weiß die Anwen-auf zweien – Portrait – dargestellt (Abb. 3). dung, ob in der Start-Activity RSSActivity ein oder zwei Ein Fragment zu erzeugen ist denkbar einfach. Die Fragmente gleichzeitig angezeigt werden sollen?“ Diezugehörige Klasse muss lediglich von der Klasse Frag- Antwort ist ganz einfach: Wir geben dies explizit vorment oder einer der existierenden Subklassen ableiten und nutzen dabei die Tatsache aus, dass Android zwi-und die entsprechenden Callback-Methoden, wie zum schen den verschiedenen Orientierungen unterscheidenBeispiel onCreate(), onStart(), onPause() und onStop(), und auf Wunsch unterschiedliche Ressourcen heranzie-implementieren. Erfahrenen Android-Entwicklern wird hen kann. In unserem Beispiel haben wir unterschied-dabei sofort die Ähnlichkeit zu den Activities und deren liche XML-Layouts für die Ausrichtungen LandscapeLifecycle auffallen. Als Basis für das eigene Fragment und Portrait hinterlegt (Listing 3 und 4).kommt neben den bereits oben erwähnten Klassen Frag- Während das Landscape-Layout zwei Fragmente,ment, DialogFragment und ListFragment noch die Klas- Liste und Details, einbindet, befindet sich im Portrait-se PreferenceFragment in Frage, deren Anwendungsfall Layout nur das Fragment der Listendarstellung. Dasselbsterklärend ist. Resource-Management des Android-Frameworks sorgt In unserem Beispiel implementieren wir zwei Frag- automatisch dafür, dass die Start-Activity RSSActivity jement-Klassen. Das erste Fragment nutzt als Basis die nach aktueller Ausrichtung das richtige Layout einbin-Klasse ListFragment und dient zur Listendarstellung des det. Nachdem diese Frage nun geklärt ist, schauen wirRSS Feeds. Das zweite Fragment leitet direkt von derKlasse Fragment ab und wird von uns zur Detaildarstel-lung eines einzelnen Feed-Elements genutzt. Listing  1zeigt die wesentlichen Teile des RSSListFragments, Lis-ting 2 die des RSSDetailFragment.ListFragmentSchauen wir uns zunächst einmal die in Listing 1 dar-gestellte Fragment-Klasse zur Listendarstellung etwasgenauer an. Wie bereits weiter oben beschrieben, passtdas RSSListFragment seinen Lifecycle an denjenigen derumliegenden Activity an. Entsprechend wird innerhalbder Callback-Methode onActivityCreated() der RSSFeed mittels einer AsyncTask und einem darin aufgeru-fenen XML Pull Parser geladen und im Anschluss mit- Abb. 3: Anwendung in Landscape und Portraitwww.android360.de 1 | 2012 android 360 81
  • USER INTERFACES | UI-FRAGMENTE uns an, wie die Verbindung der Liste zu der Detailan- zeigt, dass mittels if-Abfrage zwischen der Dual-Pane- sicht funktioniert. Dazu werfen wir noch einmal einen und der Single-Pane-Anzeige unterschieden wird. Die Blick auf Listing 1. Berechnung des booleschen Werts erfolgt dabei durch einen Zugriff auf die umliegende Activity und den Test, Qual der Wahl – Teil II ob dieses das Detail-Fragment beinhaltet und anzeigt: Selektiert der Nutzer ein Element aus der Liste, springt die Anwendung in die Callback-Methode onListItem- View rssDetails = getActivity().findViewById(R.id.rss_detail); Click(...) und ruft von dort showDetails(position) für das boolean isDualPane = rssDetails!= null && eben selektierte Element auf. Ein Blick in diese Methode rssDetails.getVisibility() == View.VISIBLE; Listing 1: Fragment zur Listendarstellung RSSDetailsFragment details = (RSSDetailsFragment) getFragmentManager().findFragmentById(R.id.rss_detail); public class RSSListFragment extends ListFragment { if (details == null || details.getShownIndex() != index) { private static final String FEED_URL = "..." // Neues Fragment erzeugen und mit Hilfe einer boolean mDualPane; // Fragment Transaction (er)setzen. int mCurCheckPosition = 0; details = RSSDetailsFragment.newInstance(index); FragmentTransaction fragmentTransaction = // Umliegende Activity wurde erzeugt getFragmentManager().beginTransaction(); public void onActivityCreated(Bundle savedInstanceState) { fragmentTransactio.replace(R.id.rss_detail, details); fragmentTransactio.setTransition( super.onActivityCreated(savedInstanceState); FragmentTransaction.TRANSIT_FRAGMENT_FADE); new AsyncFeedLoaderTask().execute(FEED_URL); fragmentTransactio.commit(); } // Check, ob wir uns im Single-Pane // oder Dual-Pane-Modus befinden. } else { View detailsFrame = getActivity().findViewById(R.id.rss_detail); // kein Dual-Pane-Modus, daher neue Activity mDualPane = detailsFrame != null // fuer Details aufrufen && detailsFrame.getVisibility() == View.VISIBLE; Intent intent = new Intent(); intent.setClass(getActivity(), RSSDetailsActivity.class); // wir sind im Dual-Pane-Modus, d.h. intent.putExtra("index", index); // Details koennen angezeigt werden. startActivity(intent); if (mDualPane) { } showDetails(mCurCheckPosition); } } } // AsyncTask für das Laden/Parsen der RSS-FEED-Daten private class AsyncFeedLoaderTask extends AsyncTask<String, Void, List<String>> { // User hat RSS-Feed-Element ausgewaehlt public void onListItemClick(ListView l, View v, // Parse RSS Feed XML im Hintergrund int position, protected List<String> doInBackground(String... urls) { long id) { List<String> rssFeedHeader = ...; showDetails(position); ... } return titles; } // Helper Methode zur Anzeige der Details void showDetails(int index) { // RSS Feed Header via ListAdapter in UI setzen mCurCheckPosition = index; protected void onPostExecute(List<String> rssFeedHeader) { setListAdapter(new ArrayAdapter<String>(getActivity(), if (mDualPane) { android.R.layout.simple_list_item_activated_1, // Zugriff auf Liste via ListAdapter rssFeedHeader)); getListView().setItemChecked(index, true); } } // end of AsyncFeedLoaderTask // Checken, ob Details-Fragment angezeigt wird } // end of RSSListFragment // UND ob es ersetzt werden muss.82 android 360 1 | 2012 www.android360.de
  • UI-FRAGMENTE | USER INTERFACESBefindet sich die Anwendung im Dual-Pane-Modus,können also beide Fragmente gleichzeitig angezeigt Listing 2: Fragment zur Detaildarstellungwerden, wird in der Methode showDetails(position) ein public class RSSDetailsFragment extends Fragment {neues RSSDetailsFragment mit dem Inhalt des ausge-wählten RSS-Feed-Elements erzeugt und anschließend in // Index des anzuzeigenden RSS Feedsdie umliegende Activity eingefügt. Für das dynamische private int shownIndex;Einfügen eines Fragments in eine Activity verwendenwir eine FragmentTransaction. Mithilfe der Transakti- ...on wird sichergestellt, dass mehrere Manipulationen aufFragmenten zu einer atomaren Operation zusammenge- // erzeugt View mit Details des RSS Feedsfasst werden: public View onCreateView(LayoutInflater inflater, ViewGroup container, RSSDetailsFragment details = RSSDetailsFragment.newInstance(index); Bundle savedInstanceState) { FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(R.id.rss_detail, details); // erzeuge View Elemente ft.commit(); ScrollView scroller = new ScrollView(getActivity()); TextView text = new TextView(getActivity());Befindet sich die Anwendung dagegen nicht im Dual- scroller.addView(text);Pane-, sondern im Single-Pane-Modus und muss somitdie Anzeige des RSSDetailsFragment in einer eigenen // setze RSS Feed DetailsActivity erfolgen, wird wie sonst auch üblich ein Intent text.setText(getRssFeed(index));erzeugt, das für den Aufruf bzw. das Starten der Activi-ty verantwortlich ist. Welches RSS-Feed-Element in der return scroller;Activity beziehungsweise dem darin enthaltenen Frag- }ment angezeigt werden soll, wird dem Intent als Para- }meter, also als „Extra“, mitgegeben: Anzeige Anzeige
  • USER INTERFACES | UI-FRAGMENTE Intent intent = new Intent(); kann nun automatisch in die umliegende Activity ein- intent.setClass(getActivity(), RSSDetailsActivity.class); gebettet werden. Wir erinnern uns, dass die umliegende intent.putExtra("index", index); Activity je nach Ausrichtung des Geräts entweder die startActivity(intent); RSSActivity (Landscape) oder aber die RSSDetailsActi- vity (Portrait) sein kann. Schauen wir uns nun auch noch einmal die Klasse RSS- DetailsFragment etwas genauer an (Listing 2). Um zu Menüs und Action Bar demonstrieren, wie ein Fragment auch ohne XML- Im Verlauf des Artikels haben wir bereits einige Paralle- Layout zur Laufzeit aufgebaut werden kann, basiert len zwischen Fragmenten und Activities kennengelernt. RSSDetailsFragment, im Gegensatz zur Klasse RSS- So verwundert es nicht, dass auch im Bereich des Menu ListFragment, nicht auf einem vordefinierten Layout, Handlings adaptierte Konzepte zu finden sind. Genau wie sondern baut die UI dynamisch auf. In der Callback- eine Activity kann auch ein Fragment mithilfe der Call- Methode onCreateView(...) wird zunächst ein Scroller back-Methode onCreateOptionMenu() einzelne Menü- erzeugt und in diesen dann ein TextView-Element plat- punkte zu einem bestehenden Menü oder einem Action ziert, das zur Anzeige des Feed-Textes dient. Die so er- Bar hinzufügen. Damit diese Methode überhaupt aufge- zeugte View wird von der Methode zurückgegeben und rufen wird, muss allerdings innerhalb der onCreate()-Me- thode des Fragments ein entsprechendes Interesse durch den Aufruf von setHasOptionMenu() signalisiert werden. Listing 3: XML-Layout für Landscape Stellen mehrere Fragmente einzelne Menüpunkte zur <LinearLayout Verfügung, setzt sich das Gesamtmenü am Ende aus xmlns:android="http://schemas.android.com/apk/res/android" dem Activity-Menü und den einzelnen Fragment-Me- android:orientation="horizontal" nüs zusammen. Bei der Abarbeitung eines selektierten android:layout_width="match_parent" Menüeintrags hat dabei zunächst die Activity Vorrang. android:layout_height="match_parent"> Nur wenn das Event nicht von der Activity verarbeitet wird, kommt das Fragment zum Zug. Natürlich lässt // Fragment fuer RSS-Feed-Liste sich neben dem beschriebenen Option-Menü auch ein <fragment Kontextmenü in einem Fragment registrieren. class="de.openknowledge.mobile.ui.RSSListFragment" android:id="@+id/rss_list" android:layout_weight="1" Fazit android:layout_width="0px" Durch die Einführung der UI-Fragmente in Android 3.0 android:layout_height="match_parent" /> für Tablet-PCs und deren allgemeine Verfügbarkeit in Android 4.0 haben die Möglichkeiten des UI-Designs // Frame fuer RSS-Feed-Detail deutlich an Flexibilität gewonnen. User Interfaces kön- <FrameLayout nen modular aufgebaut, einzelne UI-Bestandteile in android:id="@+id/rss_detail" verschiedenen Activities wiederverwendet werden. UI- android:layout_weight="1" Workflows können sich zur Laufzeit mit wenigen Zeilen android:layout_width="0px" zusätzlichen Codes optimal an die verschiedenen Ziel- android:layout_height="match_parent" Devices anpassen. Natürlich bringt die Verwendung der android:background="?android:attr/detailsElementBackground" /> neuen UI-Fragmente auch ein gewisses Umdenken für <LinearLayout UI-Designer und Entwickler mit sich. Da die Android- UI-Fragmente aber von Anfang an als embeddable Kom- ponenten konzipiert und stark an die bereits bestehenden Activities angepasst wurden, ist der Einstieg relativ ein- Listing 4: Fragment für Portrait fach. Last but not least bleibt zu erwähnen, dass dank <FrameLayout Googles „Android Compability Package“ [3] das Kon- xmlns:android="http://schemas.android.com/apk/res/android" zept der Fragmente auch in Android Apps abwärts bis Android:layout_width="match_parent" zur Version 1.6 zur Anwendung kommen kann. android:layout_height="match_parent"> Lars Röwekamp ist Geschäftsführer der open knowledge GmbH // Fragment fuer RSS-Feed-Liste und berät seit mehr als zehn Jahren Kunden in internationalen Projekten rund um das Thema Enterprise Computing (Twitter: <fragment @mobileLarson). class="de.openknowledge.mobile.ui.RSSListFragment" android:id="@+id/rss_list" android:layout_width="match_parent" Links & Literatur android:layout_height="match_parent" /> [1] Android SDK Documentation, Fragments: http://bit.ly/dMu0xu </FrameLayout> [2] Working with XML on Android: http://ibm.co/9OIfHM [3] Android Compability Package: http://bit.ly/iHJIra84 android 360 1 | 2012 www.android360.de