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

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.

Cyril Mottier

March 28, 2013
Tweet

More Decks by Cyril Mottier

Other Decks in Programming

Transcript

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

    to jpg/png Return the new Drawable YES NO
  2. Inflate from XML File ends with «.xml» Create from stream

    to jpg/png Return the new Drawable YES NO
  3. 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 }
  4. 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 }
  5. <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
  6. <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
  7. 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>
  8. 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:
  9. 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:
  10. 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
  11. 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 }
  12. 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 }
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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>
  18. 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
  19. 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
  20. 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
  21. 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>
  22. 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
  23. 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
  24. 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
  25. + + + + + + + + + +

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