Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Google Mobile Design Codelab.pdf

JasonNi
October 03, 2013

Google Mobile Design Codelab.pdf

JasonNi

October 03, 2013
Tweet

More Decks by JasonNi

Other Decks in Technology

Transcript

  1. Developer Resources Find out more: + Android Developers Android Developers

    on YouTube Android Developers Blog http://developer.android.com
  2. Codelab Format Slides, Worksheet, Code 6 Checkpoints Ask our friendly

    Teaching Assistants Material: http://bit.ly/18EhXuo
  3. Our Agenda 0: Get Set up 1: Modernising and ActionBarCompat

    2: Branding 3: Spacing and Typography 4: Tablet UI 5: Bitmap Performance 6: Threading 7: Image Caching
  4. Required Downloads IDE for Android Development: http://developer.android.com/sdk •ADT Bundle (Eclipse

    + Android SDK) •Bonus: Android Studio Android SDK, API 18 Support Library (already included in codelab archive)
  5. Checkpoint 0 Worksheet: Checkpoint 0 http://bit.ly/18EhXuo What you will do:

    •Setup IDE and environment •Import Project •Run the app
  6. EXAMPLE TREATMENT FOR DEVELOPERS AndroidManifest.xml: android:targetSdkVersion = 18 <?xml version="1.0"

    encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.xyzreader" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="18" /> ... </manifest>
  7. EXAMPLE TREATMENT FOR DEVELOPERS AndroidManifest.xml: android:targetSdkVersion = 18 Set your

    target SDK <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.xyzreader" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="18" /> ... </manifest>
  8. EXAMPLE TREATMENT FOR DEVELOPERS AndroidManifest.xml: android:targetSdkVersion = 18 Set your

    target SDK <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.xyzreader" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="18" /> ... </manifest>
  9. EXAMPLE TREATMENT FOR DEVELOPERS AndroidManifest.xml: android:targetSdkVersion = 18 <?xml version="1.0"

    encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.xyzreader" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="18" /> ... </manifest>
  10. EXAMPLE TREATMENT FOR DEVELOPERS Extend ActionBarActivity Use ActionBarCompat public class

    ArticleDetailActivity extends ActionBarActivity FragmentActivity { ... } public class ArticleListActivity extends ActionBarActivity FragmentActivity { ... }
  11. EXAMPLE TREATMENT FOR DEVELOPERS ActionBar options in ActionBarCompat: Use support-callbacks

    Use ActionBarCompat @Override public void onCreateSupportOptionsMenu(Menu menu, MenuInflater inflater) { ... } @Override public boolean onSupportOptionsItemSelected(MenuItem item) { ... }
  12. EXAMPLE TREATMENT FOR DEVELOPERS Menus in ActionBarCompat: Need to define

    your own namespace Use ActionBarCompat In your menu.xml, add the following namespace: <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/refresh" android:title="@string/refresh" android:icon="@drawable/ic_refresh" app:showAsAction="always|withText" /> <item android:id="@+id/settings" app:showAsAction="never" android:title="@string/settings"/> </menu>
  13. EXAMPLE TREATMENT FOR DEVELOPERS Menus in ActionBarCompat: Need to define

    your own namespace Use ActionBarCompat In your menu.xml, add the following namespace: <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/refresh" android:title="@string/refresh" android:icon="@drawable/ic_refresh" app:showAsAction="always|withText" /> <item android:id="@+id/settings" app:showAsAction="never" android:title="@string/settings"/> </menu>
  14. EXAMPLE TREATMENT FOR DEVELOPERS Menus in ActionBarCompat: Need to define

    your own namespace In your menu.xml, add the following namespace: <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/refresh" android:title="@string/refresh" android:icon="@drawable/ic_refresh" app:showAsAction="always|withText" /> <item android:id="@+id/settings" app:showAsAction="never" android:title="@string/settings"/> </menu>
  15. EXAMPLE TREATMENT FOR DEVELOPERS android:theme = Theme.Holo.Light.DarkActionBar Holo Theme +

    Action Bar <resources> <style name="AppBaseTheme" parent="Theme.AppCompat.Light.DarkActionBar"> </style> </resources>
  16. EXAMPLE TREATMENT FOR DEVELOPERS Application theme MUST inherit from Theme.AppCompat.*

    Styling your ActionBar <resources xmlns:android="http://schemas.android.com/apk/res/android"> <style name="Theme.Styled" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="actionBarStyle">@style/Widget.Styled.ActionBar</item> <item name="android:actionBarStyle">@style/Widget.Styled.ActionBar</item> </style> <style name="Widget.Styled.ActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid.Inverse"> <item name="background">@drawable/bg_striped</item> <item name="android:background">@drawable/bg_striped</item> </style> ... </resources>
  17. EXAMPLE TREATMENT FOR DEVELOPERS Application theme MUST inherit from Theme.AppCompat.*

    Use ActionBarCompat Styling your ActionBar <resources xmlns:android="http://schemas.android.com/apk/res/android"> <style name="Theme.Styled" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="actionBarStyle">@style/Widget.Styled.ActionBar</item> <item name="android:actionBarStyle">@style/Widget.Styled.ActionBar</item> </style> <style name="Widget.Styled.ActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid.Inverse"> <item name="background">@drawable/bg_striped</item> <item name="android:background">@drawable/bg_striped</item> </style> ... </resources>
  18. EXAMPLE TREATMENT FOR DEVELOPERS Application theme MUST inherit from Theme.AppCompat.*

    Styling your ActionBar <resources xmlns:android="http://schemas.android.com/apk/res/android"> <style name="Theme.Styled" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="actionBarStyle">@style/Widget.Styled.ActionBar</item> <item name="android:actionBarStyle">@style/Widget.Styled.ActionBar</item> </style> <style name="Widget.Styled.ActionBar" parent="Widget.AppCompat.Light.ActionBar.Solid.Inverse"> <item name="background">@drawable/bg_striped</item> <item name="android:background">@drawable/bg_striped</item> </style> ... </resources>
  19. EXAMPLE TREATMENT FOR DEVELOPERS Search Google for “Action Bar Style

    Generator”: Android Action Bar Style Generator by Jeff Gilfelt Style Compatibility AppCompat
  20. EXAMPLE TREATMENT Branded Color Scheme + App Icon FOR DEVELOPERS

    Search Google for “Action Bar Style Generator”: Android Action Bar Style Generator by Jeff Gilfelt Style Compatibility AppCompat
  21. EXAMPLE TREATMENT FOR DEVELOPERS Search Google for “Action Bar Style

    Generator”: Android Action Bar Style Generator by Jeff Gilfelt Style Compatibility AppCompat
  22. Checkpoint 2 Worksheet: Checkpoint 2 http://bit.ly/18EhXuo What you will do:

    •(Generate your own style) •Apply custom theme •Update link color
  23. <?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="thumbnail_width">80dp</dimen> <dimen name="thumbnail_height">48dp</dimen> <dimen name="photo_height">200dp</dimen>

    <dimen name="list_item_vert_margin">8dp</dimen> <dimen name="detail_horiz_margin">16dp</dimen> </resources> EXAMPLE TREATMENT FOR DEVELOPERS 48dp Rhythm set margins in dimens.xml dimens.xml
  24. <?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="thumbnail_width">80dp</dimen> <dimen name="thumbnail_height">48dp</dimen> <dimen name="photo_height">200dp</dimen>

    <dimen name="list_item_vert_margin">8dp</dimen> <dimen name="detail_horiz_margin">16dp</dimen> </resources> EXAMPLE TREATMENT FOR DEVELOPERS 48dp Rhythm set margins in dimens.xml Whitespace (Margins + Spacing) dimens.xml
  25. <?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="thumbnail_width">80dp</dimen> <dimen name="thumbnail_height">48dp</dimen> <dimen name="photo_height">200dp</dimen>

    <dimen name="list_item_vert_margin">8dp</dimen> <dimen name="detail_horiz_margin">16dp</dimen> </resources> EXAMPLE TREATMENT FOR DEVELOPERS 48dp Rhythm set margins in dimens.xml Whitespace (Margins + Spacing) dimens.xml
  26. <?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="thumbnail_width">80dp</dimen> <dimen name="thumbnail_height">48dp</dimen> <dimen name="photo_height">200dp</dimen>

    <dimen name="list_item_vert_margin">8dp</dimen> <dimen name="detail_horiz_margin">16dp</dimen> </resources> EXAMPLE TREATMENT FOR DEVELOPERS 48dp Rhythm set margins in dimens.xml dimens.xml
  27. EXAMPLE TREATMENT FOR DEVELOPERS android:scaleType = centerCrop <ImageView android:id="@+id/photo" android:layout_width="match_parent"

    android:layout_height="@dimen/photo_height" android:layout_marginLeft="@dimen/detail_horiz_margin" android:layout_marginRight="@dimen/detail_horiz_margin" android:scaleType="centerCrop" />
  28. EXAMPLE TREATMENT FOR DEVELOPERS android:scaleType = centerCrop Thumbnail + Photo

    Treatment <ImageView android:id="@+id/photo" android:layout_width="match_parent" android:layout_height="@dimen/photo_height" android:layout_marginLeft="@dimen/detail_horiz_margin" android:layout_marginRight="@dimen/detail_horiz_margin" android:scaleType="centerCrop" />
  29. EXAMPLE TREATMENT FOR DEVELOPERS android:scaleType = centerCrop Thumbnail + Photo

    Treatment <ImageView android:id="@+id/photo" android:layout_width="match_parent" android:layout_height="@dimen/photo_height" android:layout_marginLeft="@dimen/detail_horiz_margin" android:layout_marginRight="@dimen/detail_horiz_margin" android:scaleType="centerCrop" />
  30. EXAMPLE TREATMENT FOR DEVELOPERS android:scaleType = centerCrop <ImageView android:id="@+id/photo" android:layout_width="match_parent"

    android:layout_height="@dimen/photo_height" android:layout_marginLeft="@dimen/detail_horiz_margin" android:layout_marginRight="@dimen/detail_horiz_margin" android:scaleType="centerCrop" />
  31. EXAMPLE TREATMENT Custom Font More spacing Ellipsized text Limited, Fixed

    number of lines All caps Deemphasized colour for sub headings
  32. EXAMPLE TREATMENT Custom Font More spacing Ellipsized text Limited, Fixed

    number of lines All caps Deemphasized colour for sub headings Typography
  33. EXAMPLE TREATMENT Custom Font More spacing Ellipsized text Limited, Fixed

    number of lines All caps Deemphasized colour for sub headings
  34. EXAMPLE TREATMENT <TextView android:id="@+id/article_title" style="?android:textAppearanceMedium" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#c000" android:fontFamily="sans-serif-condensed" android:textStyle="bold"

    android:ellipsize="end" android:maxLines="2" android:lineSpacingMultiplier="0.85" android:paddingBottom="4dp" /> <TextView android:id="@+id/article_subtitle" style="?android:textAppearanceSmall" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#6000" android:textAllCaps="true" android:maxLines="1" android:singleLine="true" android:ellipsize="end" /> FOR DEVELOPERS android:fontFamily = sans-serif-condensed (or -light) android:lineSpacingMultiplier android:textStyle android:ellipsize = end android:maxLines android:singleLine = true android:textAllCaps = true
  35. EXAMPLE TREATMENT Typography <TextView android:id="@+id/article_title" style="?android:textAppearanceMedium" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#c000" android:fontFamily="sans-serif-condensed"

    android:textStyle="bold" android:ellipsize="end" android:maxLines="2" android:lineSpacingMultiplier="0.85" android:paddingBottom="4dp" /> <TextView android:id="@+id/article_subtitle" style="?android:textAppearanceSmall" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#6000" android:textAllCaps="true" android:maxLines="1" android:singleLine="true" android:ellipsize="end" /> FOR DEVELOPERS android:fontFamily = sans-serif-condensed (or -light) android:lineSpacingMultiplier android:textStyle android:ellipsize = end android:maxLines android:singleLine = true android:textAllCaps = true
  36. EXAMPLE TREATMENT Typography <TextView android:id="@+id/article_title" style="?android:textAppearanceMedium" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#c000" android:fontFamily="sans-serif-condensed"

    android:textStyle="bold" android:ellipsize="end" android:maxLines="2" android:lineSpacingMultiplier="0.85" android:paddingBottom="4dp" /> <TextView android:id="@+id/article_subtitle" style="?android:textAppearanceSmall" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#6000" android:textAllCaps="true" android:maxLines="1" android:singleLine="true" android:ellipsize="end" /> FOR DEVELOPERS android:fontFamily = sans-serif-condensed (or -light) android:lineSpacingMultiplier android:textStyle android:ellipsize = end android:maxLines android:singleLine = true android:textAllCaps = true
  37. EXAMPLE TREATMENT <TextView android:id="@+id/article_title" style="?android:textAppearanceMedium" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#c000" android:fontFamily="sans-serif-condensed" android:textStyle="bold"

    android:ellipsize="end" android:maxLines="2" android:lineSpacingMultiplier="0.85" android:paddingBottom="4dp" /> <TextView android:id="@+id/article_subtitle" style="?android:textAppearanceSmall" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#6000" android:textAllCaps="true" android:maxLines="1" android:singleLine="true" android:ellipsize="end" /> FOR DEVELOPERS android:fontFamily = sans-serif-condensed (or -light) android:lineSpacingMultiplier android:textStyle android:ellipsize = end android:maxLines android:singleLine = true android:textAllCaps = true
  38. EXAMPLE TREATMENT FOR DEVELOPERS android:textColorLink = @color/bacon Custom code @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_article_detail, container, false); if (mItem != null) { ((TextView) rootView.findViewById(R.id.article_title)) .setText(mItem.title); // Custom highlight the author ((TextView) rootView.findViewById(R.id.article_byline)) .setText(Html.fromHtml(mItem.time.toUpperCase() + " BY <font color='" + getResources().getString(R.string.author_font_color) + "'>" + mItem.author.toUpperCase() + "</a>")); // Use custom font ((TextView) rootView.findViewById(R.id.article_body)) .setTypeface(Typeface.createFromAsset( getResources().getAssets(), "Rosario-Regular.ttf")); ... } return rootView; }
  39. EXAMPLE TREATMENT FOR DEVELOPERS android:textColorLink = @color/bacon Custom code Custom

    Highlight + Font @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_article_detail, container, false); if (mItem != null) { ((TextView) rootView.findViewById(R.id.article_title)) .setText(mItem.title); // Custom highlight the author ((TextView) rootView.findViewById(R.id.article_byline)) .setText(Html.fromHtml(mItem.time.toUpperCase() + " BY <font color='" + getResources().getString(R.string.author_font_color) + "'>" + mItem.author.toUpperCase() + "</a>")); // Use custom font ((TextView) rootView.findViewById(R.id.article_body)) .setTypeface(Typeface.createFromAsset( getResources().getAssets(), "Rosario-Regular.ttf")); ... } return rootView; }
  40. EXAMPLE TREATMENT FOR DEVELOPERS android:textColorLink = @color/bacon Custom code Custom

    Highlight + Font @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_article_detail, container, false); if (mItem != null) { ((TextView) rootView.findViewById(R.id.article_title)) .setText(mItem.title); // Custom highlight the author ((TextView) rootView.findViewById(R.id.article_byline)) .setText(Html.fromHtml(mItem.time.toUpperCase() + " BY <font color='" + getResources().getString(R.string.author_font_color) + "'>" + mItem.author.toUpperCase() + "</a>")); // Use custom font ((TextView) rootView.findViewById(R.id.article_body)) .setTypeface(Typeface.createFromAsset( getResources().getAssets(), "Rosario-Regular.ttf")); ... } return rootView; }
  41. EXAMPLE TREATMENT FOR DEVELOPERS android:textColorLink = @color/bacon Custom code @Override

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_article_detail, container, false); if (mItem != null) { ((TextView) rootView.findViewById(R.id.article_title)) .setText(mItem.title); // Custom highlight the author ((TextView) rootView.findViewById(R.id.article_byline)) .setText(Html.fromHtml(mItem.time.toUpperCase() + " BY <font color='" + getResources().getString(R.string.author_font_color) + "'>" + mItem.author.toUpperCase() + "</a>")); // Use custom font ((TextView) rootView.findViewById(R.id.article_body)) .setTypeface(Typeface.createFromAsset( getResources().getAssets(), "Rosario-Regular.ttf")); ... } return rootView; }
  42. Checkpoint 3 Worksheet: Checkpoint 3 http://bit.ly/18EhXuo What you will do:

    •Update whitespace (padding and margins) •Fix image thumbnails and photos •Update Typography •Custom highlighting and font
  43. EXAMPLE TREATMENT FOR DEVELOPERS Guides: “Designing for Multiple Screens” and

    “Building a Dynamic UI with Fragments” Two-pane UI
  44. EXAMPLE TREATMENT FOR DEVELOPERS Landscape tablet resources: values-sw600dp-land Reusable references:

    refs.xml <resources> <!-- For more on layout aliases, see: http://developer.android.com/training/multiscreen/ screensizes.html#TaskUseAliasFilters --> <item name="activity_article_list" type="layout"> @layout/activity_article_twopane </item> </resources> refs.xml
  45. EXAMPLE TREATMENT FOR DEVELOPERS Landscape tablet resources: values-sw600dp-land Reusable references:

    refs.xml Two-pane UI <resources> <!-- For more on layout aliases, see: http://developer.android.com/training/multiscreen/ screensizes.html#TaskUseAliasFilters --> <item name="activity_article_list" type="layout"> @layout/activity_article_twopane </item> </resources> refs.xml
  46. EXAMPLE TREATMENT FOR DEVELOPERS Landscape tablet resources: values-sw600dp-land Reusable references:

    refs.xml <resources> <!-- For more on layout aliases, see: http://developer.android.com/training/multiscreen/ screensizes.html#TaskUseAliasFilters --> <item name="activity_article_list" type="layout"> @layout/activity_article_twopane </item> </resources> refs.xml
  47. EXAMPLE TREATMENT <?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="thumbnail_width">96dp</dimen> <dimen name="photo_height">400dp</dimen>

    <dimen name="list_item_vert_margin">16dp</dimen> <dimen name="detail_horiz_margin">80dp</dimen> </resources> dimens.xml FOR DEVELOPERS Landscape tablet resources: values-sw600dp-land Tablet-specific dimensions: dimens.xml
  48. EXAMPLE TREATMENT Two-pane UI with better spacing <?xml version="1.0" encoding="utf-8"?>

    <resources> <dimen name="thumbnail_width">96dp</dimen> <dimen name="photo_height">400dp</dimen> <dimen name="list_item_vert_margin">16dp</dimen> <dimen name="detail_horiz_margin">80dp</dimen> </resources> dimens.xml FOR DEVELOPERS Landscape tablet resources: values-sw600dp-land Tablet-specific dimensions: dimens.xml
  49. EXAMPLE TREATMENT Two-pane UI with better spacing <?xml version="1.0" encoding="utf-8"?>

    <resources> <dimen name="thumbnail_width">96dp</dimen> <dimen name="photo_height">400dp</dimen> <dimen name="list_item_vert_margin">16dp</dimen> <dimen name="detail_horiz_margin">80dp</dimen> </resources> dimens.xml FOR DEVELOPERS Landscape tablet resources: values-sw600dp-land Tablet-specific dimensions: dimens.xml
  50. EXAMPLE TREATMENT <?xml version="1.0" encoding="utf-8"?> <resources> <dimen name="thumbnail_width">96dp</dimen> <dimen name="photo_height">400dp</dimen>

    <dimen name="list_item_vert_margin">16dp</dimen> <dimen name="detail_horiz_margin">80dp</dimen> </resources> dimens.xml FOR DEVELOPERS Landscape tablet resources: values-sw600dp-land Tablet-specific dimensions: dimens.xml
  51. Checkpoint 4 Worksheet: Checkpoint 4 http://bit.ly/18EhXuo What you will do:

    •Add tablet layout •Tablet-optimized whitespace
  52. EXAMPLE TREATMENT FOR DEVELOPERS BitmapFactory.Options: options.inSampleSize = 16 (or use

    smaller images) @Override public View getView(int position, View convertView, ViewGroup container) { if (convertView == null) { convertView = LayoutInflater.from(getActivity()) .inflate(R.layout.list_item_article, container, false); } ... BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 16; Bitmap b = BitmapFactory.decodeResource(getResources(), item.photoResId, options); ((ImageView) convertView.findViewById(R.id.thumbnail)).setImageBitmap(b); return convertView; }
  53. EXAMPLE TREATMENT FOR DEVELOPERS BitmapFactory.Options: options.inSampleSize = 16 (or use

    smaller images) Bitmap Performance Tuning @Override public View getView(int position, View convertView, ViewGroup container) { if (convertView == null) { convertView = LayoutInflater.from(getActivity()) .inflate(R.layout.list_item_article, container, false); } ... BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 16; Bitmap b = BitmapFactory.decodeResource(getResources(), item.photoResId, options); ((ImageView) convertView.findViewById(R.id.thumbnail)).setImageBitmap(b); return convertView; }
  54. EXAMPLE TREATMENT FOR DEVELOPERS BitmapFactory.Options: options.inSampleSize = 16 (or use

    smaller images) Bitmap Performance Tuning @Override public View getView(int position, View convertView, ViewGroup container) { if (convertView == null) { convertView = LayoutInflater.from(getActivity()) .inflate(R.layout.list_item_article, container, false); } ... BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 16; Bitmap b = BitmapFactory.decodeResource(getResources(), item.photoResId, options); ((ImageView) convertView.findViewById(R.id.thumbnail)).setImageBitmap(b); return convertView; }
  55. EXAMPLE TREATMENT FOR DEVELOPERS BitmapFactory.Options: options.inSampleSize = 16 (or use

    smaller images) @Override public View getView(int position, View convertView, ViewGroup container) { if (convertView == null) { convertView = LayoutInflater.from(getActivity()) .inflate(R.layout.list_item_article, container, false); } ... BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 16; Bitmap b = BitmapFactory.decodeResource(getResources(), item.photoResId, options); ((ImageView) convertView.findViewById(R.id.thumbnail)).setImageBitmap(b); return convertView; }
  56. EXAMPLE TREATMENT FOR DEVELOPERS options.inJustDecodeBounds = true; options.inSampleSize = 16

    (or use smaller images) public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }
  57. EXAMPLE TREATMENT FOR DEVELOPERS options.inJustDecodeBounds = true; options.inSampleSize = 16

    (or use smaller images) Dynamically calculate inSampleSize public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }
  58. EXAMPLE TREATMENT FOR DEVELOPERS options.inJustDecodeBounds = true; options.inSampleSize = 16

    (or use smaller images) Dynamically calculate inSampleSize public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }
  59. EXAMPLE TREATMENT FOR DEVELOPERS options.inJustDecodeBounds = true; options.inSampleSize = 16

    (or use smaller images) public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); }
  60. EXAMPLE TREATMENT FOR DEVELOPERS calculate optimal sample size for required

    size public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 16; if (reqWidth == 0 || reqHeight == 0) return inSampleSize; if (height > reqHeight || width > reqWidth) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; }
  61. EXAMPLE TREATMENT FOR DEVELOPERS calculate optimal sample size for required

    size Dynamically calculate inSampleSize public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 16; if (reqWidth == 0 || reqHeight == 0) return inSampleSize; if (height > reqHeight || width > reqWidth) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; }
  62. EXAMPLE TREATMENT FOR DEVELOPERS calculate optimal sample size for required

    size public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 16; if (reqWidth == 0 || reqHeight == 0) return inSampleSize; if (height > reqHeight || width > reqWidth) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; }
  63. Checkpoint 5 Worksheet: Checkpoint 5 http://bit.ly/18EhXuo What you will do:

    •Load bitmaps using ‘sampleSize’ •Set ‘inJustDecodeBounds’ parameter
  64. EXAMPLE TREATMENT FOR DEVELOPERS AsyncTask class BitmapWorkerTask extends AsyncTask<Integer, Void,

    Bitmap> { private final WeakReference<ImageView> imageViewReference; private int resId = 0; public BitmapWorkerTask(ImageView imageView) { // Use a WeakReference to ensure the ImageView can // be garbage collected imageViewReference = new WeakReference<ImageView>(imageView); } // Decode image in background. @Override protected Bitmap doInBackground(Integer... params) { resId = params[0]; ImageView thumbnail = imageViewReference.get(); Bitmap bitmap = decodeSampledBitmapFromResource( getResources(), resId, thumbnail.getWidth(), thumbnail.getHeight()); addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); return bitmap; } ...
  65. EXAMPLE TREATMENT FOR DEVELOPERS AsyncTask Load images concurrently off the

    Main(UI) Thread class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> { private final WeakReference<ImageView> imageViewReference; private int resId = 0; public BitmapWorkerTask(ImageView imageView) { // Use a WeakReference to ensure the ImageView can // be garbage collected imageViewReference = new WeakReference<ImageView>(imageView); } // Decode image in background. @Override protected Bitmap doInBackground(Integer... params) { resId = params[0]; ImageView thumbnail = imageViewReference.get(); Bitmap bitmap = decodeSampledBitmapFromResource( getResources(), resId, thumbnail.getWidth(), thumbnail.getHeight()); addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); return bitmap; } ...
  66. EXAMPLE TREATMENT FOR DEVELOPERS AsyncTask Load images concurrently off the

    Main(UI) Thread class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> { private final WeakReference<ImageView> imageViewReference; private int resId = 0; public BitmapWorkerTask(ImageView imageView) { // Use a WeakReference to ensure the ImageView can // be garbage collected imageViewReference = new WeakReference<ImageView>(imageView); } // Decode image in background. @Override protected Bitmap doInBackground(Integer... params) { resId = params[0]; ImageView thumbnail = imageViewReference.get(); Bitmap bitmap = decodeSampledBitmapFromResource( getResources(), resId, thumbnail.getWidth(), thumbnail.getHeight()); addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); return bitmap; } ...
  67. EXAMPLE TREATMENT FOR DEVELOPERS AsyncTask class BitmapWorkerTask extends AsyncTask<Integer, Void,

    Bitmap> { private final WeakReference<ImageView> imageViewReference; private int resId = 0; public BitmapWorkerTask(ImageView imageView) { // Use a WeakReference to ensure the ImageView can // be garbage collected imageViewReference = new WeakReference<ImageView>(imageView); } // Decode image in background. @Override protected Bitmap doInBackground(Integer... params) { resId = params[0]; ImageView thumbnail = imageViewReference.get(); Bitmap bitmap = decodeSampledBitmapFromResource( getResources(), resId, thumbnail.getWidth(), thumbnail.getHeight()); addBitmapToMemoryCache(String.valueOf(params[0]), bitmap); return bitmap; } ...
  68. EXAMPLE TREATMENT FOR DEVELOPERS AsyncTask ... // Once complete, see

    if ImageView is still around and set bitmap. @Override protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null && bitmap != null) { final ImageView imageView = imageViewReference.get(); final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (this == bitmapWorkerTask && imageView != null) { imageView.setImageBitmap(bitmap); } } } }
  69. EXAMPLE TREATMENT FOR DEVELOPERS AsyncTask Load images concurrently off the

    Main(UI) Thread ... // Once complete, see if ImageView is still around and set bitmap. @Override protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null && bitmap != null) { final ImageView imageView = imageViewReference.get(); final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (this == bitmapWorkerTask && imageView != null) { imageView.setImageBitmap(bitmap); } } } }
  70. EXAMPLE TREATMENT FOR DEVELOPERS AsyncTask ... // Once complete, see

    if ImageView is still around and set bitmap. @Override protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null && bitmap != null) { final ImageView imageView = imageViewReference.get(); final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); if (this == bitmapWorkerTask && imageView != null) { imageView.setImageBitmap(bitmap); } } } }
  71. EXAMPLE TREATMENT FOR DEVELOPERS LruCache private LruCache<String, Bitmap> mMemoryCache; //

    Instantiate in the onCreate() method public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); }
  72. EXAMPLE TREATMENT FOR DEVELOPERS LruCache Use Image Cache private LruCache<String,

    Bitmap> mMemoryCache; // Instantiate in the onCreate() method public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); }
  73. EXAMPLE TREATMENT FOR DEVELOPERS LruCache Use Image Cache private LruCache<String,

    Bitmap> mMemoryCache; // Instantiate in the onCreate() method public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); }
  74. EXAMPLE TREATMENT FOR DEVELOPERS LruCache private LruCache<String, Bitmap> mMemoryCache; //

    Instantiate in the onCreate() method public void addBitmapToMemoryCache(String key, Bitmap bitmap) { if (getBitmapFromMemCache(key) == null) { mMemoryCache.put(key, bitmap); } } public Bitmap getBitmapFromMemCache(String key) { return mMemoryCache.get(key); }
  75. EXAMPLE TREATMENT FOR DEVELOPERS LruCache calculate cache size in sizeOf(..)

    // Get max available VM memory in kilobytes, exceeding this amount // will throw an OutOfMemory exception. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // Use 1/8th of the available memory for this memory cache. final int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override protected int sizeOf(String key, Bitmap bitmap) { // The cache size in kilobytes rather than if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR1) { return bitmap.getByteCount() / 1024; } else { return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } } };
  76. EXAMPLE TREATMENT FOR DEVELOPERS LruCache calculate cache size in sizeOf(..)

    Use Image Cache // Get max available VM memory in kilobytes, exceeding this amount // will throw an OutOfMemory exception. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // Use 1/8th of the available memory for this memory cache. final int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override protected int sizeOf(String key, Bitmap bitmap) { // The cache size in kilobytes rather than if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR1) { return bitmap.getByteCount() / 1024; } else { return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } } };
  77. EXAMPLE TREATMENT FOR DEVELOPERS LruCache calculate cache size in sizeOf(..)

    Use Image Cache // Get max available VM memory in kilobytes, exceeding this amount // will throw an OutOfMemory exception. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // Use 1/8th of the available memory for this memory cache. final int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override protected int sizeOf(String key, Bitmap bitmap) { // The cache size in kilobytes rather than if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR1) { return bitmap.getByteCount() / 1024; } else { return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } } };
  78. EXAMPLE TREATMENT FOR DEVELOPERS LruCache calculate cache size in sizeOf(..)

    // Get max available VM memory in kilobytes, exceeding this amount // will throw an OutOfMemory exception. final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // Use 1/8th of the available memory for this memory cache. final int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1) @Override protected int sizeOf(String key, Bitmap bitmap) { // The cache size in kilobytes rather than if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR1) { return bitmap.getByteCount() / 1024; } else { return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } } };
  79. Thank you! A few simple techniques: Backwards Compatibility using Support

    Library Design, Spacing, Typography Improve app performance Interested to find out more? developer.android.com +Android Developers