MTC13 Android UIs für alle(s)

69
Android UIs für alle(s) Konzepte für die adaptive UI-Entwicklung Andreas Hölzl Canoo Engineering AG Thursday, March 14, 13

description

Slide to my MobileTechCon 2013 talk in Munich on Android multi-screen support, see http://nextlevelandroid.com/?p=252

Transcript of MTC13 Android UIs für alle(s)

Page 1: 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

Page 2: MTC13 Android UIs für alle(s)

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

Page 3: MTC13 Android UIs für alle(s)

Wer bin ich?

3

@andywoodly

Thursday, March 14, 13

Page 4: MTC13 Android UIs für alle(s)

Fragmentierung ... Differenzierung ...

4

Eric Schmidt, CES 2012:“Differentiation is positive, fragmentation is negative.”

Thursday, March 14, 13

Page 5: MTC13 Android UIs für alle(s)

Fragmentierung ... Differenzierung ...

5

http://www.forbes.com/sites/limyunghui/2012/03/27/android-fragmentation-and-condoms/

Thursday, March 14, 13

Page 6: MTC13 Android UIs für alle(s)

Auflösungsunabhängigkeit

Thursday, March 14, 13

Page 7: MTC13 Android UIs für alle(s)

Auflösungsabhängigkeit

7

low density medium density high density

low density high density

Thursday, March 14, 13

Page 8: MTC13 Android UIs für alle(s)

Auflösungs un abhängigkeit

8

low density high density

low density medium density high density

Thursday, March 14, 13

Page 9: MTC13 Android UIs für alle(s)

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

Page 10: MTC13 Android UIs für alle(s)

๏ [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

Page 11: MTC13 Android UIs für alle(s)

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

Page 12: MTC13 Android UIs für alle(s)

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

Page 13: MTC13 Android UIs für alle(s)

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

Page 14: MTC13 Android UIs für alle(s)

14

Auflösungsklassen

๏ Tooling (Eclipse, ADT Plugin 20.0.0+)

Thursday, March 14, 13

Page 15: MTC13 Android UIs für alle(s)

15

Auflösungsklassen

๏ Tooling (Eclipse, ADT Plugin 20.0.0+)

Thursday, March 14, 13

Page 16: MTC13 Android UIs für alle(s)

16

Auflösungsklassen

๏ Tooling (Eclipse, ADT Plugin 20.0.0+)

Thursday, March 14, 13

Page 17: MTC13 Android UIs für alle(s)

17

Auflösungsklassen

๏ Tooling (Android Asset Studio)

Thursday, March 14, 13

Page 18: MTC13 Android UIs für alle(s)

18

Auflösungsklassen

๏ Lint

http://tools.android.com/tips/lint-checks

Thursday, March 14, 13

Page 19: MTC13 Android UIs für alle(s)

19

Auflösungsklassen

๏ Marktdaten

http://developer.android.com/about/dashboards/index.html

October 1, 2012

Thursday, March 14, 13

Page 20: MTC13 Android UIs für alle(s)

Multi-Screen-Support

Thursday, March 14, 13

Page 21: MTC13 Android UIs für alle(s)

21

http://www.google.de/nexus/

Thursday, March 14, 13

Page 22: MTC13 Android UIs für alle(s)

22

Thursday, March 14, 13

Page 23: MTC13 Android UIs für alle(s)

23

Screen Sizes

Bildschirmgrösse (inch)

Grössenklasse

2 4 7 10

small normal large xlarge

Thursday, March 14, 13

Page 24: MTC13 Android UIs für alle(s)

Multi-Screen-Support

24

Ziel: korrektes Resize-Verhalten

Thursday, March 14, 13

Page 25: MTC13 Android UIs für alle(s)

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

Page 26: MTC13 Android UIs für alle(s)

Multi-Screen-Support

26

๏ korrektes Resizing‣ geschachtelte LinearLayout vermeiden‣ RelativeLayout verwenden

LinearLayout (vertical)|- LinearLayout (horizontal)|- LinearLayout (horizontal)

RelativeLayout

Thursday, March 14, 13

Page 27: MTC13 Android UIs für alle(s)

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

Page 28: MTC13 Android UIs für alle(s)

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

Page 29: MTC13 Android UIs für alle(s)

29

Skalierbare Grafiken

๏ Beispiel Nine-Patch Image - action bar shadow

Versionen für mdpi, hdpi, xhdpi erforderlich

Thursday, March 14, 13

Page 30: MTC13 Android UIs für alle(s)

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

Page 31: MTC13 Android UIs für alle(s)

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

Page 32: MTC13 Android UIs für alle(s)

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

Page 33: MTC13 Android UIs für alle(s)

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

Page 34: MTC13 Android UIs für alle(s)

34

Multi-Screen-Support - Tooling

Thursday, March 14, 13

Page 35: MTC13 Android UIs für alle(s)

Fragments

A fragment a day

keeps the fragmentation at bay!

Thursday, March 14, 13

Page 36: MTC13 Android UIs für alle(s)

36

Fragments

Thursday, March 14, 13

Page 37: MTC13 Android UIs für alle(s)

37

✔ wiederverwendbare (UI-)Komponente✔ “Sub-Activity”✔ eigener Lifecycle✔ immer an Activity gebunden✔ lose Kopplung

Fragments

Thursday, March 14, 13

Page 38: MTC13 Android UIs für alle(s)

38

Fragments - Anwendungsprinzip

๏ Fragment‣ UI-Komponente

๏ Activity-Layout (XML)‣ verwendet Fragments

๏ Activity-Klasse‣ Inter-Fragment-Logik

๏ XML-Ressourcen‣ “Switch”

Thursday, March 14, 13

Page 39: MTC13 Android UIs für alle(s)

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

Page 40: MTC13 Android UIs für alle(s)

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

Page 41: MTC13 Android UIs für alle(s)

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

Page 42: MTC13 Android UIs für alle(s)

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

Page 43: MTC13 Android UIs für alle(s)

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

Page 44: MTC13 Android UIs für alle(s)

44

Fragments/Activity - Kommunikation

notify

listen toActivity A Fragment A

๏ Listener Pattern‣ wiederverwertbare Komponenten‣ lose Kopplung

setter

Thursday, March 14, 13

Page 46: MTC13 Android UIs für alle(s)

Fragmentspre 3.0

happy path

Thursday, March 14, 13

Page 48: MTC13 Android UIs für alle(s)

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

Page 49: MTC13 Android UIs für alle(s)

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

Page 50: MTC13 Android UIs für alle(s)

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

Page 51: MTC13 Android UIs für alle(s)

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

Page 52: MTC13 Android UIs für alle(s)

Design Pattern

Thursday, March 14, 13

Page 53: MTC13 Android UIs für alle(s)

53

Design Pattern

Show / HideAusblenden eines Fragments, Rück-Navigation mittels Up-Action.

Thursday, March 14, 13

Page 54: MTC13 Android UIs für alle(s)

54

Design Pattern

Stretch/compressFragments passen sich in der Breite an.

Thursday, March 14, 13

Page 55: MTC13 Android UIs für alle(s)

55

Design Pattern

Expand / CollapseAktive Komponente erhält mehr Platz.

Thursday, March 14, 13

Page 56: MTC13 Android UIs für alle(s)

56

Design Pattern

StackNeuanordnung der Fragments (v.a. bei Orientierungswechsel).

Thursday, March 14, 13

Page 57: MTC13 Android UIs für alle(s)

57

Design Pattern

“Tabs To Columns”Tabs / ViewPages werden nebeneinander dargestellt.

https://code.google.com/p/iosched/

Thursday, March 14, 13

Page 58: MTC13 Android UIs für alle(s)

Tooling

Thursday, March 14, 13

Page 59: MTC13 Android UIs für alle(s)

59

Tooling - Eclipse

Multi-configuration editing

RelativeLayout support, spacing defaults

Asset wizard

New activity wizard

Lint integration

Thursday, March 14, 13

Page 60: MTC13 Android UIs für alle(s)

60

Tooling - Monitor, DDMS (screen snapshot)

$ ./tools/monitor

Hilfreich bei dynamischen Layouts/Fragments

Thursday, March 14, 13

Page 61: MTC13 Android UIs für alle(s)

61

Tooling - Monitor, Hierarchyviewer

$ ./tools/monitor

nur Emulator / developer devices

Thursday, March 14, 13

Page 62: MTC13 Android UIs für alle(s)

Summary

Thursday, March 14, 13

Page 63: MTC13 Android UIs für alle(s)

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

Page 64: MTC13 Android UIs für alle(s)

Ressourcen

Thursday, March 14, 13

Page 65: MTC13 Android UIs für alle(s)

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

Page 66: MTC13 Android UIs für alle(s)

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

Page 67: MTC13 Android UIs für alle(s)

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

Page 68: MTC13 Android UIs für alle(s)

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

Page 69: MTC13 Android UIs für alle(s)

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