Design Patterns for Tablets and Smartphones

3,073 views

Published on

This is a talk I gave at AnDevCon. It talks about ways to take advantage of features introduced in Android 3.0 to create more modular and better looking apps.

Published in: Technology, Business
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,073
On SlideShare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
132
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Design Patterns for Tablets and Smartphones

    1. 1. Design Patterns for Tablets and Smartphones Michael Galpin, Bump Technologies
    2. 2. About me• Apps! • Bump • eBay Mobile• Book! • Android in Practice • Chapter 15
    3. 3. Agenda • Key Concepts • App Structure • Fragments • Goodies • Action Bar • Loaders • Eye Candy
    4. 4. So you built an app...
    5. 5. One app or two?•Re-use code & assets •Simpler logic•Build on Market presence •New platform features
    6. 6. Library Projects
    7. 7. Breakin’ it down App
    8. 8. Breakin’ it downApp Tablet App Library
    9. 9. What’s in a Library?• I/O: Networking, files, content • Data parsing• Models• Services, Receivers, Content Providers• Resources • Drawables, Strings
    10. 10. Moving Targets
    11. 11. <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.manning.aip.tabdroid" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="11" /> <supports-screens android:smallScreens="false" android:normalScreens="false" android:largeScreens="true" android:xlargeScreens="true" android:requiresSmallestWidthDp="500" />
    12. 12. <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.manning.aip.tabdroid" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="11" /> <supports-screens android:smallScreens="false" android:normalScreens="false" android:largeScreens="true" API <= 12 android:xlargeScreens="true" android:requiresSmallestWidthDp="500" />
    13. 13. <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.manning.aip.tabdroid" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="11" /> <supports-screens android:smallScreens="false" android:normalScreens="false" android:largeScreens="true" android:xlargeScreens="true" /> android:requiresSmallestWidthDp="500" API >= 13
    14. 14. Not all tablets are created equally
    15. 15. Screen Size Selectors
    16. 16. Have your cake and eat it too
    17. 17. Multiple APKsApp Tablet App Library
    18. 18. Multiple APKs MyApp on the MarketApp Tablet App Library
    19. 19. Fragments
    20. 20. Stop me if you’ve heard this one
    21. 21. Fragment
    22. 22. Fragment
    23. 23. Fragment
    24. 24. Fragment
    25. 25. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/details_container"> <fragment class="com.manning.aip.tabdroid.SectionDetailsFragment" android:id="@+id/section_list_fragment" android:visibility="gone" android:layout_marginTop="?android:attr/actionBarSize" android:layout_width="300dp" android:layout_height="match_parent" /> <fragment class="com.manning.aip.tabdroid.DealFragment" android:id="@+id/deal_fragment" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
    26. 26. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/details_container" android:gravity="bottom"> <fragment class="com.manning.aip.tabdroid.DealFragment" android:id="@+id/deal_fragment" android:layout_marginTop="?android:attr/actionBarSize" android:layout_width="match_parent" android:layout_height="wrap_content" /> <fragment class="com.manning.aip.tabdroid.FilmstripFragment" android:id="@+id/section_filmstrip_fragment" android:visibility="gone" android:layout_width="match_parent" android:layout_height="300dp" android:layout_gravity="bottom"/></LinearLayout>
    27. 27. Fragments: Not just for Tablets• “Smart” UI • Stateful • Mange data (state)• Communicates
    28. 28. Spot the Fragment
    29. 29. Communication & Couplingpublic class SectionDetailsFragment extends ListFragment { private void showDeal(int position){ app.currentItem = app.currentSection.items.get(position); DealFragment fragment = (DealFragment) getFragmentManager().findFragmentById(R.id.deal_fragment); fragment.showCurrentItem(); } @Override public void onListItemClick(ListView l, View v, int position, long id) { currentPosition = position; showDeal(position); }...}
    30. 30. Who knows you & who do you know?Fragment Activity Fragment
    31. 31. Use an Observerpublic class SectionDetailsFragment extends ListFragment { OnItemSelectedListener listener; public static interface OnItemSelectedListener { public void onItemSelected(Item item); } public void setOnItemSelectedListener( OnItemSelectedListener listener){ this.listener = listener; } private void showDeal(int position){ app.currentItem = app.currentSection.items.get(position); listener.onItemSelected(app.currentItem); }...}
    32. 32. ...and Observepublic class DealsMain extends Activity implements OnItemSelectedListener{ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.home); SectionDetailsFragment sectionFragment = (SectionDetailsFragment) getFragmentManager().findFragmentById(R.id.section_list_fragment); sectionFragment.setOnItemSelectedListener(this); } @Override public void onItemSelected(Item item) { DealFragment fragment = (DealFragment) getFragmentManager().findFragmentById(R.id.deal_fragment); fragment.showItem(item); }...}
    33. 33. QueuesFragment Activity Fragment inbound outbound
    34. 34. QueuesFragment Activity Fragment inbound outbound
    35. 35. Queues (Handlers)Fragment Activity Fragment inbound outbound
    36. 36. But I have to supportAndroid 2.1
    37. 37. The Action Bar
    38. 38. ActionBar Essentials• Replaces Menu• Can be top & bottom in ICS• Not available in Compatibility Package • Helper for menus -> ActionBar
    39. 39. Loaders
    40. 40. Threads
    41. 41. HandlersThreads
    42. 42. AsyncTask HandlersThreads
    43. 43. AsyncTaskLoader AsyncTask HandlersThreads
    44. 44. Why do I need Loaders? • Encapsulates • Loading of data • Caching of data • Updates to data • Cursors and Async
    45. 45. Eye Candy
    46. 46. Drag and Drop
    47. 47. class BoxDragListener implements OnDragListener{ boolean insideOfMe = false; Drawable border = null; Drawable redBorder = getResources().getDrawable(R.drawable.border3); @Override public boolean onDrag(View self, DragEvent event) { if (event.getAction() == DragEvent.ACTION_DRAG_STARTED){ border = self.getBackground(); self.setBackgroundDrawable(redBorder); } else if (event.getAction() == DragEvent.ACTION_DRAG_ENTERED){ insideOfMe = true; } else if (event.getAction() == DragEvent.ACTION_DRAG_EXITED){ insideOfMe = false; } else if (event.getAction() == DragEvent.ACTION_DROP){ if (insideOfMe){ // add to container } else if (event.getAction() == DragEvent.ACTION_DRAG_ENDED){ self.setBackgroundDrawable(border); } return true; }}
    48. 48. public class DndActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.grid); findViewById(R.id.topLeft).setOnDragListener(new BoxDragListener()); findViewById(R.id.bottomLeft).setOnDragListener(new BoxDragListener()); findViewById(R.id.topRight).setOnDragListener(new BoxDragListener()); findViewById(R.id.bottomRight).setOnDragListener(new BoxDragListener()); }... ImageView imgView = (ImageView) recycledView; imgView.setOnLongClickListener(new OnLongClickListener(){ @Override public boolean onLongClick(View view) { ClipData data = ClipData.newPlainText("foo","bar"); DragShadowBuilder shadowBuilder = new DragShadowBuilder(owner); owner.startDrag(data, shadowBuilder, owner, 0); return true; } });}
    49. 49. AnimatorsImageView backgroundImage = (count % 2 == 0) ? rightSlide : leftSlide;ObjectAnimator anim = ObjectAnimator.ofFloat(backgroundImage, "alpha", 0.0f, 1.0f);anim.addListener(new AnimatorListenerAdapter(){ public void onAnimationEnd(Animator animator){ nextSlide(); }});

    ×