MTC13 Android UIs für alle(s)
-
Upload
andreas-hoelzl -
Category
Technology
-
view
105 -
download
0
description
Transcript of MTC13 Android UIs für alle(s)
Android UIs für alle(s)Konzepte für die adaptive UI-Entwicklung
Andreas HölzlCanoo Engineering AG
Thursday, March 14, 13
Agenda
๏ Grundlagen‣ Auflösungsunabhängigkeit‣ Multi-Screen-Support
๏ Fragments‣ phone ∪ tablet
2
๏ Best Practices‣ Design Pattern
๏ Tooling‣ ADK, Eclipse
๏ Ressourcen
2244 unterschiedliche Geräte - 1 Code-Basis
Ziel: Alles Wichtige in 1h, sonst ...
Thursday, March 14, 13
Wer bin ich?
3
@andywoodly
Thursday, March 14, 13
Fragmentierung ... Differenzierung ...
4
Eric Schmidt, CES 2012:“Differentiation is positive, fragmentation is negative.”
Thursday, March 14, 13
Fragmentierung ... Differenzierung ...
5
http://www.forbes.com/sites/limyunghui/2012/03/27/android-fragmentation-and-condoms/
Thursday, March 14, 13
Auflösungsunabhängigkeit
Thursday, March 14, 13
Auflösungsabhängigkeit
7
low density medium density high density
low density high density
Thursday, March 14, 13
Auflösungs un abhängigkeit
8
low density high density
low density medium density high density
Thursday, March 14, 13
Auflösungs un abhängigkeit
9
Bei Grössenangaben immer dp verwenden!
px dp
๏ Ursache der Abhängigkeit: px
๏ Lösung: dp / sp (devices independent pixel)
... sp für Textgrössen
Thursday, March 14, 13
๏ [l|m|h|xh]dpi - generalized densities
Auflösungsklassen
10
~120dpi ~160dpi ~240dpi ~320dpi
Auflösung (dpi)
Auflösungsklasse
100 200 300
ldpi mdpi hdpi xhdpi
tvdpi xxhdpi
Thursday, March 14, 13
Auflösungsklassen
11
๏ Skalierungsfaktoren
xhdpi launcher icon (nexus 10)
48
38
72
96
144
launcher iconpx
3:4:6:8 Verhältnis
Thursday, March 14, 13
12
Auflösungsklassen
/res/drawable ist nur für XML!
Grafiken immer in Ordner mit
Auflösungs-Klassifizierer verwalten
๏ Projekt-Ressourcen
drawable-120dpi
drawable-160dpi
drawable-240dpi
drawable-320dpi
drawable-480dpi
?
Thursday, March 14, 13
Auflösungs un abhängigkeit
13
Resources res = getResources();
DisplayMetrics metrics = res.getDisplayMetrics();
float scale = metrics.density;
px
๏ Problem: px -basierte APIs?
๏ Lösung: DisplayMetrics.density
Thursday, March 14, 13
14
Auflösungsklassen
๏ Tooling (Eclipse, ADT Plugin 20.0.0+)
Thursday, March 14, 13
15
Auflösungsklassen
๏ Tooling (Eclipse, ADT Plugin 20.0.0+)
Thursday, March 14, 13
16
Auflösungsklassen
๏ Tooling (Eclipse, ADT Plugin 20.0.0+)
Thursday, March 14, 13
17
Auflösungsklassen
๏ Tooling (Android Asset Studio)
Thursday, March 14, 13
18
Auflösungsklassen
๏ Lint
http://tools.android.com/tips/lint-checks
Thursday, March 14, 13
19
Auflösungsklassen
๏ Marktdaten
http://developer.android.com/about/dashboards/index.html
October 1, 2012
Thursday, March 14, 13
Multi-Screen-Support
Thursday, March 14, 13
21
http://www.google.de/nexus/
Thursday, March 14, 13
22
Thursday, March 14, 13
23
Screen Sizes
Bildschirmgrösse (inch)
Grössenklasse
2 4 7 10
small normal large xlarge
Thursday, March 14, 13
Multi-Screen-Support
24
Ziel: korrektes Resize-Verhalten
Thursday, March 14, 13
Multi-Screen-Support
25
<LinearLayout android:id="@+id/linearLayout1" android:layout_height="50dp" android:layout_width="match_parent" android:gravity="center">
<ImageView android:id="@+id/imageView1" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="0" android:paddingRight="30dp" android:layout_gravity="left" android:src="@drawable/logo" />
<View android:id="@+id/view1" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_weight="1" />
<Button android:id="@+id/categorybutton" android:background="@drawable/button_bg" android:layout_height="match_parent" android:layout_width="120dp" android:layout_weight="0" />
</LinearLayout>
๏ korrektes Resizing‣ fixe Dimensionsangaben nur
wo sinnvoll‣ match_parent verwenden‣ wrap_content verwenden
Thursday, March 14, 13
Multi-Screen-Support
26
๏ korrektes Resizing‣ geschachtelte LinearLayout vermeiden‣ RelativeLayout verwenden
LinearLayout (vertical)|- LinearLayout (horizontal)|- LinearLayout (horizontal)
RelativeLayout
Thursday, March 14, 13
Multi-Screen-Support
27
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="Very Long Text" />
<EditText android:id="@+id/editText1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_toRightOf="@+id/textView1" />
<TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/editText1" android:text="Text" />
<EditText android:id="@+id/editText2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/editText1" >
</EditText>
</RelativeLayout>
๏ RelativeLayout
Thursday, March 14, 13
28
Skalierbare Grafiken
๏ Nine-Patch Images
http://android-ui-utils.googlecode.com/hg/asset-studio/dist/nine-patches.html
<sdk>/tools/draw9patch
Thursday, March 14, 13
29
Skalierbare Grafiken
๏ Beispiel Nine-Patch Image - action bar shadow
Versionen für mdpi, hdpi, xhdpi erforderlich
Thursday, March 14, 13
Multi-Screen-Support
30
Ziel: Screen-optimierte Layouts
small
normal
res/layout/my_layout.xml
res/layout-small/my_layout.xml
Thursday, March 14, 13
Multi-Screen-Support
31
res/layout/my_layout.xml // normal screen size ("default")res/layout-small/my_layout.xml // small screen sizeres/layout-large/my_layout.xml // large screen sizeres/layout-xlarge/my_layout.xml // extra large screen sizeres/layout-xlarge-land/my_layout.xml // extra large in landscape orientation
๏ optimierte Ressourcen‣ screen size qualifier (small, normal, large, xlarge)‣ orientation qualifier (port, land)‣ locale, etc. qualifier
@Deprecated
Thursday, March 14, 13
Multi-Screen-Support
32
๏ optimierte Ressourcen‣ sw<N>dp‣ w<N>dp, h<N>dp
res/layout/main_activity.xml # smaller than 600dp available widthres/layout-sw600dp/main_activity.xml # For 7” tablets (600dp wide and bigger)res/layout-sw720dp/main_activity.xml # For 10” tablets (720dp wide and bigger)
seit 3.2
res/layout/main_activity.xml # smaller than 600dp available widthres/layout-w600dp/main_activity.xml # any screen with >=600dp available
Die allermeisten Tablets verwenden >=3.2
res/layout/main_activity.xml # For phonesres/layout-xlarge/main_activity.xml # For pre-3.2 tabletsres/layout-sw600dp/main_activity.xml # For 3.2 and up tablets
Thursday, March 14, 13
33
Screen Sizes - Smallest Width
320dp 480dp 600dp 720dp
res/layout/main_activity.xml # For phonesres/layout-sw600dp/main_activity.xml # For tablet
res/layout-sw720dp/main_activity.xml # For 10” tablets
res/layout-w600dp/main_activity.xml # Multi-pane when enough width
Best practice
Thursday, March 14, 13
34
Multi-Screen-Support - Tooling
Thursday, March 14, 13
Fragments
A fragment a day
keeps the fragmentation at bay!
Thursday, March 14, 13
36
Fragments
Thursday, March 14, 13
37
✔ wiederverwendbare (UI-)Komponente✔ “Sub-Activity”✔ eigener Lifecycle✔ immer an Activity gebunden✔ lose Kopplung
Fragments
Thursday, March 14, 13
38
Fragments - Anwendungsprinzip
๏ Fragment‣ UI-Komponente
๏ Activity-Layout (XML)‣ verwendet Fragments
๏ Activity-Klasse‣ Inter-Fragment-Logik
๏ XML-Ressourcen‣ “Switch”
Thursday, March 14, 13
39
Fragments - Resourcen-Switch
res/layout/main.xml
res/layout-w600dp/main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" >
<fragment android:name="com.example.android.FragmentA" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" />
<fragment android:name="com.example.android.FragmentB" android:layout_width="0dp" android:layout_weight="2" android:layout_height="match_parent" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" >
<fragment android:name="com.example.android.FragmentA" android:layout_width="match_parent" android:layout_height="match_parent" />
</LinearLayout>
Thursday, March 14, 13
40
Fragments - Anwendung
res/layout/main.xml
res/layout-w600dp/main.xml
Activity A
src/
Activity B
Fragment A
Fragment B
Intent:Activity B
Activity A event
UpdateFragment B
Fragment B sichtbar?
Ja
Nein
Activity AFragment A
Fragment B
Thursday, March 14, 13
41
Fragments - Implementierung
Activity A
src/
Activity B
Fragment A
Fragment B
Activity AFragment A
Fragment B
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
// find our fragments mFragmentA = (FragmentA) getFragmentManager().findFragmentById(R.id.fragment_a); mFragmentB = (FragmentB) getFragmentManager().findFragmentById(R.id.fragment_b);
// Determine whether we are in single-pane or dual-pane mIsDualPane = mFragmentB != null; }
ActivityA.java
@Override public void onItemSelected(int index) { if (mIsDualPane) { // display it on the article fragment mFragmentB.displayStuff(...); } else { // use separate activity Intent i = new Intent(this, ActivityB.class); i.putExtra("stuff", ...); startActivity(i); } }
Thursday, March 14, 13
42
Fragments - Implementierung II
Activity A
src/
Activity B
Fragment A
Fragment B
Activity AFragment A
Fragment B
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ...
// Determine whether we are in single-pane or dual-pane mIsDualPane = getResources().getBoolean(R.bool.has_two_panes) }
ActivityA.java
Alternativer Layout-Switch
<resources> <bool name="has_two_panes">false</bool></resources>
<resources> <bool name="has_two_panes">true</bool></resources>
res/values/layouts.xml
res/values-w600dp/layouts.xml
Thursday, March 14, 13
43
Fragments - Implementierung III programmatisch
FragmentTransaction ftx = getFragmentManager().beginTransaction();
DetailFragment fragment = new DetailFragment();ftx.add(R.id.fragment_container, fragment);
ftx.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);ftx.addToBackStack(null); ftx.commit();
add(), remove(), replace(), show(), hide()
kein remove(), replace() auf XML-deklarierten Fragments!
Thursday, March 14, 13
44
Fragments/Activity - Kommunikation
notify
listen toActivity A Fragment A
๏ Listener Pattern‣ wiederverwertbare Komponenten‣ lose Kopplung
setter
Thursday, March 14, 13
Fragments - Lifecycle
45
onAttach()Activity/Context steht zur Verfügung.
onCreate()Initialisierung essentieller Komponenten, welcher während paused, stopped, resumed beibehalten werden sollen.
onCreateView()Initialisierung der Fragment-(Main)View (LayoutInflater).
onPause()Speicherung aller Zustände, die über die aktuelle Session persistiert werden sollen.
Thursday, March 14, 13
Fragmentspre 3.0
happy path
Thursday, March 14, 13
๏ pre 3.0 devices
‣ <sdk>/extras/android/support/v4/android-support-v4.jar.http://developer.android.com/tools/extras/support-library.html
Support Library
47
• FragmentActivity• Fragment• FragmentManager• FragmentTransaction• ListFragment• DialogFragment
FragmentActivity.getSupportFragmentManager()
Thursday, March 14, 13
Support Library + Fragments + Map (pre Maps v2)
48
“Maps + Fragments +
Support package =
headache”
http://nextlevelandroid.com/?p=114
public class MapFragment extends LocalActivityManagerFragment { private TabHost mTabHost;
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.map_fragment, container, false); mTabHost = (TabHost) view.findViewById(android.R.id.tabhost); mTabHost.setup(getLocalActivityManager()); TabSpec tab = mTabHost.newTabSpec("map") .setIndicator("map") .setContent(new Intent(getActivity(), MyMapActivity.class)); mTabHost.addTab(tab); /* * hack!!! * view hierarchy is: * PhomeWindow$DecorView$.../FrameLayout/LinearLayout/MapView * findViewById() does not work directly on tab content view */ mMapView = (MyMapView) mTabHost.getTabContentView().getChildAt(0).findViewById(R.id.mapview); ...
return view; }
public class LocalActivityManagerFragment extends Fragment {
private static final String KEY_STATE_BUNDLE = "localActivityManagerState"; private LocalActivityManager mLocalActivityManager; protected LocalActivityManager getLocalActivityManager() { return mLocalActivityManager; }
...}
Problem: MapView ⇔ MapActivity
Thursday, March 14, 13
Support Library + MapFragment (Maps v2)
49
<fragment class="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent"/>
Installation über Google Play Services SDK
Google Maps Android API v2
The Google Maps Android API
v2 Utopiahttp://android.cyrilmottier.com/?p=855
Thursday, March 14, 13
Support Library + MapFragment + ActionbarSherlock
50
ActionbarSherlock-Erweiterung notwendig
public class SherlockMapFragment extends SupportMapFragment {}
http://stackoverflow.com/questions/13721929/using-actionbarsherlock-with-the-new-supportmapfragment
Thursday, March 14, 13
Nested Fragments
๏ seit November 2012, Version 4.2
51
Unterstützt nur programmatische Verwendung von Fragments
Child Fragment: getChildFragmentManager()
Asynchrone Initialisierung notwendig
(Bsp.: Fragment mit ViewPager mit
Fragments)
private class SetAdapterTask extends AsyncTask<Void,Void,Void>{ protected Void doInBackground(Void... params) { return null; }
@Override protected void onPostExecute(Void result) { mViewPager.setAdapter(mPagerAdapter); mViewPager.setCurrentItem(mSelectedTab); mViewPager.setOffscreenPageLimit(3); } }
ViewPagerFragment
Thursday, March 14, 13
Design Pattern
Thursday, March 14, 13
53
Design Pattern
Show / HideAusblenden eines Fragments, Rück-Navigation mittels Up-Action.
Thursday, March 14, 13
54
Design Pattern
Stretch/compressFragments passen sich in der Breite an.
Thursday, March 14, 13
55
Design Pattern
Expand / CollapseAktive Komponente erhält mehr Platz.
Thursday, March 14, 13
56
Design Pattern
StackNeuanordnung der Fragments (v.a. bei Orientierungswechsel).
Thursday, March 14, 13
57
Design Pattern
“Tabs To Columns”Tabs / ViewPages werden nebeneinander dargestellt.
https://code.google.com/p/iosched/
Thursday, March 14, 13
Tooling
Thursday, March 14, 13
59
Tooling - Eclipse
Multi-configuration editing
RelativeLayout support, spacing defaults
Asset wizard
New activity wizard
Lint integration
Thursday, March 14, 13
60
Tooling - Monitor, DDMS (screen snapshot)
$ ./tools/monitor
Hilfreich bei dynamischen Layouts/Fragments
Thursday, March 14, 13
61
Tooling - Monitor, Hierarchyviewer
$ ./tools/monitor
nur Emulator / developer devices
Thursday, March 14, 13
Summary
Thursday, March 14, 13
63
Cheat Sheet
✔ dp Dimensionen
✔ Auflösungsspezifische Bild-Ressourcen
✔ wrap_content, match_parent
✔ RelativeLayout✔ Screen-optimierte Layouts
✔ Wiederverwendung durch Fragments
✔ Tooling Support nutzen - Lint
✔ Design Pattern beachten
✔ an guten Apps orientieren
✔ Dokumentation / Style Guide lesen
Thursday, March 14, 13
Ressourcen
Thursday, March 14, 13
65
๏ Official Documentation‣ Android Design Guide
http://developer.android.com/design/index.html
‣ Supporting Multiple Screenshttp://developer.android.com/guide/practices/screens_support.html
‣ New tools for managing screen sizeshttp://android-developers.blogspot.de/2011/07/new-tools-for-managing-screen-sizes.html
‣ Designing for Multiple Screenshttp://developer.android.com/training/multiscreen/index.html
‣ Multi-pane Layoutshttp://developer.android.com/design/patterns/multi-pane-layouts.html
‣ Building a Dynamic UI with Fragmentshttp://developer.android.com/training/basics/fragments/index.html
‣ Android Lint Toolhttp://tools.android.com/tips/linthttp://developer.android.com/tools/help/lint.htmlhttp://developer.android.com/tools/debugging/improving-w-lint.html
Ressourcen I
Thursday, March 14, 13
66
๏ App Clinichttp://goo.gl/piLXJ
๏ Android Design in Action - Android Developershttp://goo.gl/skOPDhttp://goo.gl/JGB4e
๏ Android Asset Studiohttp://android-ui-utils.googlecode.com/hg/asset-studio/dist/index.html
Ressourcen II
Thursday, March 14, 13
67
๏ Google I/O‣ Schedule app
https://code.google.com/p/iosched/
‣ What's New in Android Developers' Toolshttp://www.youtube.com/watch?v=Erd2k6EKxCQ
‣ Multi-Versioning Android User Interfaceshttp://www.youtube.com/watch?v=amZM8oZBgfk
‣ Designing and Implementing Android UIs for Phones and Tabletshttp://www.youtube.com/watch?v=WGIU2JX1U5Y
Ressourcen III
Thursday, March 14, 13
68
๏ Juhani Lehtimäki‣ Smashing Android UI
http://www.androiduipatterns.com/http://eu.wiley.com/WileyCDA/WileyTitle/productCd-1118387287,descCd-buy.html
๏ Others‣ Cyrill Mottier
http://android.cyrilmottier.com
‣ Android 4 - UI Design - Lars Röwekamphttp://www.openknowledge.de/publikationen/vortraege/mtc-2012/android-4-ui-design.html
‣ Flexibles UI-Design - Lars Röwekamphttp://it-republik.de/jaxenter/artikel/Flexibles-UI-Design-4770.html
‣ Deep dive into responsive mobile design - Kirill Grouchnikovhttp://www.pushing-pixels.org/2011/11/08/deep-dive-into-responsive-mobile-design-part-1.html
Ressourcen IV
Thursday, March 14, 13
69
๏ Apps mit beispielhaftem Design‣ Google I/O 2012
https://code.google.com/p/iosched/
‣ Gmailcom.google.android.gm
‣ TEDcom.ted.android
‣ Evernotecom.evernote
‣ Flipboardflipboard.app
‣ Pulsecom.alphonso.pulse
Ressourcen V
‣ Prixingfr.epicdream.beamy
‣ Pattrnorg.lucasr.pattrn
‣ Glimmrcom.bourke.glimmr
‣ The Vergecom.verge.android
Thursday, March 14, 13