Mastering Android Drawables

Mastering Android Drawables

Over the past few years, the quality of apps in the Google Play Store has increased substantially. Developers are taking Android UI seriously and producing beautiful apps made of tons of graphics resources (Bitmaps, 9-patches, shapes, etc.) every day. To avoid developers the pain of handling all types of resources, the Android framework provides the Drawable abstraction.

In this session we will deep dive into the android.graphics.drawable package and how the framework uses it internally to render scalable and responsive UIs. The Drawable notion is essential to the creation of UIs on Android but developers usually only scratch the surface of it. The class will help you to understand how framework-provided and custom Drawables can be used to make both your code cleaner and your app better, smoother and more polished.

E9bf8f6d5480ea2a2623df7dccfd1f70?s=128

Cyril Mottier

March 28, 2013
Tweet

Transcript

  1. 4.
  2. 9.
  3. 10.
  4. 12.
  5. 14.
  6. 27.
  7. 36.

    Inflate from XML File ends with «.xml» Create from stream

    to jpg/png Return the new Drawable YES NO
  8. 37.

    Inflate from XML File ends with «.xml» Create from stream

    to jpg/png Return the new Drawable YES NO
  9. 39.

    1 @Override 2 public void onCreate(Bundle savedInstanceState) { 3 super.onCreate(savedInstanceState);

    4 5 Resources r = getResources(); 6 Drawable d1 = r.getDrawable(R.drawable.ic_launcher); 7 Drawable d2 = r.getDrawable(R.drawable.ic_launcher); 8 9 Log.d(LOG_TAG, "d1: " + d1); 10 Log.d(LOG_TAG, "d2: " + d2); 11 }
  10. 43.
  11. 45.
  12. 46.

    1 @Override 2 public void onCreate(Bundle savedInstanceState) { 3 super.onCreate(savedInstanceState);

    4 5 Resources r = getResources(); 6 Drawable d1 = r.getDrawable(R.drawable.ic_launcher); 7 Drawable d2 = r.getDrawable(R.drawable.ic_launcher); 8 9 Log.d(LOG_TAG, "d1.cs: " + d1.getConstantState()); 10 Log.d(LOG_TAG, "d2.cs: " + d2.getConstantState()); 11 }
  13. 51.
  14. 54.
  15. 56.

    <selector /> StateListDrawable <level-list /> <layer-list /> <transition /> <color

    /> <shape /> <scale /> <clip /> <rotate /> <animation-list /> <inset /> <bitmap /> <nine-patch /> LevelListDrawable LayerDrawable TransitionDrawable ColorDrawable GradientDrawable ScaleDrawable ClipDrawable RotateDrawable AnimationDrawable InsetDrawable BitmapDrawable NinePatchDrawable
  16. 57.

    <selector /> StateListDrawable <level-list /> <layer-list /> <transition /> <color

    /> <shape /> <scale /> <clip /> <rotate /> <animation-list /> <inset /> <bitmap /> <nine-patch /> LevelListDrawable LayerDrawable TransitionDrawable ColorDrawable GradientDrawable ScaleDrawable ClipDrawable RotateDrawable AnimationDrawable InsetDrawable BitmapDrawable NinePatchDrawable <stupid-tag /> Resources.NotFoundException
  17. 63.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <selector 3 xmlns:android="http://schemas.android.com/apk/res/android"> 4 <item

    android:state_pressed="true"> 5 <color android:color="@color/highlight" /> 6 </item> 7 <item> 8 <color android:color="@android:color/transparent" /> 9 </item> 10 </selector>
  18. 64.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <selector 3 xmlns:android="http://schemas.android.com/apk/res/android"> 4 <item

    android:state_pressed="true"> 5 <color android:color="@color/highlight" /> 6 </item> 7 <item> 8 <color android:color="@android:color/transparent" /> 9 </item> 10 </selector> On Jly Bn:
  19. 65.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <selector 3 xmlns:android="http://schemas.android.com/apk/res/android"> 4 <item

    android:state_pressed="true"> 5 <color android:color="@color/highlight" /> 6 </item> 7 <item> 8 <color android:color="@android:color/transparent" /> 9 </item> 10 </selector> On Ggbad:
  20. 66.
  21. 68.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <selector 3 xmlns:android="http://schemas.android.com/apk/res/android"> 4 5

    <item android:state_pressed="true"> 6 <shape android:shape="rectangle"> 7 <solid android:color="@color/highlight" /> 8 </shape> 9 </item> 10 <item> 11 <color android:color="@android:color/transparent" /> 12 </item> 13 </selector> Use a solid col GraditDrawab std
  22. 72.

    1 public class DrawableView extends View { 2 private Drawable

    mDrawable; 3 4 public DrawableView(Context context) { super(context); } 5 6 public void setDrawable(Drawable d) { 7 if (d != mDrawable) { 8 mDrawable = d; 9 if (d != null) { 10 updateDrawableBounds(); 11 } 12 } 13 } 14 15 /** Update Drawable bounds with Drawable.setBounds(int, int, int, int) */ 16 private void updateDrawableBounds() { /* ... */ } 17 18 @Override 19 protected void onDraw(Canvas canvas) { 20 super.onDraw(canvas); 21 if (mDrawable != null) { 22 mDrawable.draw(canvas); 23 } 24 } 25 }
  23. 75.
  24. 77.

    1 public interface Callback { 2 public void invalidateDrawable(Drawable who);

    3 4 public void scheduleDrawable(Drawable who, 5 Runnable what, 6 long when); 7 8 public void unscheduleDrawable(Drawable who, 9 Runnable what); 10 }
  25. 80.

    1 public void setDrawable(Drawable d) { 2 if (d !=

    mDrawable) { 3 if (mDrawable != null) { 4 mDrawable.setCallback(null); 5 } 6 mDrawable = d; 7 if (d != null) { 8 d.setCallback(this); 9 updateDrawableBounds(); 10 } 11 } 12 } 13 14 @Override 15 protected boolean verifyDrawable(Drawable who) { 16 return super.verifyDrawable(who) || who == mDrawable; 17 } Ungt  pvus caback  avoid aks
  26. 81.

    1 public void setDrawable(Drawable d) { 2 if (d !=

    mDrawable) { 3 if (mDrawable != null) { 4 mDrawable.setCallback(null); 5 } 6 mDrawable = d; 7 if (d != null) { 8 d.setCallback(this); 9 updateDrawableBounds(); 10 } 11 } 12 } 13 14 @Override 15 protected boolean verifyDrawable(Drawable who) { 16 return super.verifyDrawable(who) || who == mDrawable; 17 } Regt  cut view   new caback
  27. 82.

    1 public void setDrawable(Drawable d) { 2 if (d !=

    mDrawable) { 3 if (mDrawable != null) { 4 mDrawable.setCallback(null); 5 } 6 mDrawable = d; 7 if (d != null) { 8 d.setCallback(this); 9 updateDrawableBounds(); 10 } 11 } 12 } 13 14 @Override 15 protected boolean verifyDrawable(Drawable who) { 16 return super.verifyDrawable(who) || who == mDrawable; 17 } D’t fget  ca  sup meod
  28. 85.

    1 <activity 2 android:name="LoginActivity" 3 android:label="@string/app_name" 4 android:theme="@android:style/Theme.Holo.Light.NoActionBar"> 5 <intent-filter>

    6 <action android:name="android.intent.action.MAIN" /> 7 <category android:name="android.intent.category.LAUNCHER" /> 8 </intent-filter> 9 </activity> AndroidManifest.xml In
  29. 86.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4

    android:layout_height="match_parent" 5 android:background="@color/app_background" 6 android:padding="8dp"> 7 8 <ImageView 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:layout_marginBottom="24dp" 12 android:layout_gravity="center" 13 android:src="@drawable/logo" /> 14 15 <LinearLayout 16 android:layout_width="match_parent" 17 android:layout_height="48dp" 18 android:layout_gravity="bottom" 19 android:orientation="horizontal"> 20 21 <Button 22 android:layout_width="0dp" 23 android:layout_height="fill_parent" 24 android:layout_weight="1" 25 android:text="@string/sign_up" /> 26 27 <Button 28 android:layout_width="0dp" 29 android:layout_height="fill_parent" 30 android:layout_weight="1" 31 android:text="@string/sign_in" /> 32 33 </LinearLayout> 34 35 </FrameLayout>
  30. 87.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4

    android:layout_height="match_parent" 5 android:background="@color/app_background" 6 android:padding="8dp"> 7 8 <ImageView 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:layout_marginBottom="24dp" 12 android:layout_gravity="center" 13 android:src="@drawable/logo" /> 14 15 <LinearLayout 16 android:layout_width="match_parent" 17 android:layout_height="48dp" 18 android:layout_gravity="bottom" 19 android:orientation="horizontal"> 20 21 <Button 22 android:layout_width="0dp" 23 android:layout_height="fill_parent" 24 android:layout_weight="1" 25 android:text="@string/sign_up" /> 26 27 <Button 28 android:layout_width="0dp" 29 android:layout_height="fill_parent" 30 android:layout_weight="1" 31 android:text="@string/sign_in" /> 32 33 </LinearLayout> 34 35 </FrameLayout> Use  almt uss rt FrameLayt  hold  backgr
  31. 88.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4

    android:layout_height="match_parent" 5 android:background="@color/app_background" 6 android:padding="8dp"> 7 8 <ImageView 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:layout_marginBottom="24dp" 12 android:layout_gravity="center" 13 android:src="@drawable/logo" /> 14 15 <LinearLayout 16 android:layout_width="match_parent" 17 android:layout_height="48dp" 18 android:layout_gravity="bottom" 19 android:orientation="horizontal"> 20 21 <Button 22 android:layout_width="0dp" 23 android:layout_height="fill_parent" 24 android:layout_weight="1" 25 android:text="@string/sign_up" /> 26 27 <Button 28 android:layout_width="0dp" 29 android:layout_height="fill_parent" 30 android:layout_weight="1" 31 android:text="@string/sign_in" /> 32 33 </LinearLayout> 34 35 </FrameLayout> T logo c be csid   backgr
  32. 89.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4

    android:layout_height="match_parent" 5 android:background="@color/app_background" 6 android:padding="8dp"> 7 8 <ImageView 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:layout_marginBottom="24dp" 12 android:layout_gravity="center" 13 android:src="@drawable/logo" /> 14 15 <LinearLayout 16 android:layout_width="match_parent" 17 android:layout_height="48dp" 18 android:layout_gravity="bottom" 19 android:orientation="horizontal"> 20 21 <Button 22 android:layout_width="0dp" 23 android:layout_height="fill_parent" 24 android:layout_weight="1" 25 android:text="@string/sign_up" /> 26 27 <Button 28 android:layout_width="0dp" 29 android:layout_height="fill_parent" 30 android:layout_weight="1" 31 android:text="@string/sign_in" /> 32 33 </LinearLayout> 34 35 </FrameLayout> «Sign Up/In» bus e  ly actual ctt
  33. 93.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="match_parent"

    5 android:layout_height="48dp" 6 android:layout_gravity="bottom" 7 android:layout_margin="8dp" 8 android:orientation="horizontal"> 9 10 <Button 11 android:layout_width="0dp" 12 android:layout_height="fill_parent" 13 android:layout_weight="1" 14 android:text="@string/sign_up" /> 15 16 <Button 17 android:layout_width="0dp" 18 android:layout_height="fill_parent" 19 android:layout_weight="1" 20 android:text="@string/sign_in" /> 21 22 </LinearLayout>
  34. 94.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <layer-list 3 xmlns:android="http://schemas.android.com/apk/res/android"> 4 5

    <item> 6 <shape android:shape="rectangle"> 7 <solid 8 android:color="@color/app_background" /> 9 </shape> 10 </item> 11 12 <item 13 android:bottom="48dp"> 14 <bitmap 15 android:src="@drawable/logo" 16 android:gravity="center" /> 17 </item> 18 19 </layer-list> Backgr col wh ct logo  p
  35. 95.

    1 <activity 2 android:name="LoginActivity" 3 android:label="@string/app_name" 4 android:theme="@style/Theme.Default.NoActionBar"> 5 <intent-filter>

    6 <action android:name="android.intent.action.MAIN" /> 7 <category android:name="android.intent.category.LAUNCHER" /> 8 </intent-filter> 9 </activity> AndroidManifest.xml In
  36. 96.

    1 <?xml version="1.0" encoding="utf-8"?> 2 <resources> 3 4 <style 5

    name="Theme.Default.NoActionBar" 6 parent="@android:style/Theme.Holo.Light.NoActionBar"> 7 <item name="android:windowBackground">@drawable/login</item> 8 </style> 9 10 </resources> res/values/themes.xml In
  37. 99.

    + + + + + + + + + +

    + + + + + + + + + + + + + + + Mimiz yt & be uhg im