$30 off During Our Annual Pro Sale. View Details »

Using styles and themes without going crazy

Using styles and themes without going crazy

Presented at Droidcon NYC 2015.

Daniel Lew

August 27, 2015
Tweet

More Decks by Daniel Lew

Other Decks in Programming

Transcript

  1. Using styles and themes without going
    crazy
    Dan Lew

    View Slide

  2. • No style

    • Style



    
<br/><item name="android:background">#FF0000</item>
<br/>

    View Slide

  3. When to style
    • Semantically identical Views
    • All styled Views should
    change at once

    View Slide

  4. When NOT to style
    • Single-use styles
    • Coincidentally using the same attributes
    android:id="@+id/title"

    android:textColor="@color/blue_200"

    android:textColorHint=“@color/grey_500" />


    android:id="@+id/body"

    android:textColor="@color/blue_200"

    android:textColorHint=“@color/grey_500" />

    View Slide

  5. When NOT to style
    • Single-use styles
    • Coincidentally using the same attributes
    android:id="@+id/title"

    android:textColor="@color/blue_200"

    android:textColorHint=“@color/grey_500" />


    android:id="@+id/body"

    android:textColor="@color/blue_200"

    android:textColorHint=“@color/grey_500" />

    View Slide

  6. When NOT to style
    • Single-use styles
    • Coincidentally using the same attributes
    android:id="@+id/title"

    android:textColor="@color/blue_200"

    android:textColorHint=“@color/grey_500" />


    android:id="@+id/body"

    android:textColor="@color/blue_200"

    android:textColorHint=“@color/grey_500" />

    View Slide

  7. static final int NUM_COLUMNS = 3;


    static final int NUM_RETRIES = 3;
    static final int NUM_THREE = 3;

    View Slide

  8. // static final int NUM_COLUMNS = 3;


    // static final int NUM_RETRIES = 3;

    static final int NUM_THREE = 3;

    View Slide

  9. No style?
    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:scaleType="centerCrop"

    android:src="@drawable/image"

    />
    No problem!

    View Slide

  10. View Slide

  11. View Slide

  12. Inheritance

    View Slide

  13. • Parent

    • Explicit child

    • Implicit child

    View Slide

  14. Custody Battle




    • Who gets the child?
    • Choices:
    • Both
    • Implicit
    • Explicit

    View Slide

  15. View Slide

  16. Avoid mixing implicit
    and explicit parenting

    View Slide

  17. style="@style/Widget.Button.Calculator"

    />
    name="Widget.Button.Calculator"

    parent="Widget.AppCompat.Button.Borderless"
    />

    View Slide

  18. style="@style/Widget.Button.Calculator"

    />
    name="Widget.Button.Calculator"

    parent="Widget.HahaFooledYou.Sucker"
    />

    View Slide

  19. • Explicit parent -> dotless child
    parent="Widget.AppCompat.Button.Borderless" />
    • Fake it!
    parent="Widget.AppCompat.Button" />


    parent="Widget.AppCompat.Button.Borderless" />

    View Slide

  20. Multiple Styles

    View Slide

  21. IMPOSSIBLE
    …except for TextAppearance!
    Image source: https://goo.gl/meSNFL

    View Slide

  22. TextAppearance Attributes
    • textColor
    • textColorHighlight
    • textColorHint
    • textColorLink
    • textSize
    • textStyle
    • fontFamily
    • typeface
    • textAllCaps
    • shadowColor
    • shadowDx
    • shadowDy
    • shadowRadius
    • elegantTextHeight
    • letterSpacing
    • fontFeatureSettings

    View Slide

  23. TextAppearance
    • In action
    style="@style/MyStyle"

    android:textAppearance="@style/MyText"

    />
    • Always inherit TextAppearance!
    
<br/><item name="android:textColor">#F00</item>
<br/>

    View Slide

  24. Themes!
    • Write a whole lot of UX code at once!
    • Setup defaults for everything!
    • Activity-level theming!
    • Configure system-created Views!
    • Theme swapping!

    View Slide

  25. Themes vs. Styles
    • Same thing!
    
<br/><item name="android:background">#FF0000</item>
<br/>
    
<br/><item name="android:statusBarColor">@color/blue_200</item>
<br/>
    • Different scope
    • Different attributes

    View Slide

  26. Do not mix up styles
    and themes

    View Slide

  27. Themes in Manifest
    • Application
    android:theme="@style/Theme.AppCompat">
    • Activity
    android:theme="@style/Theme.AppCompat.Light">

    View Slide

  28. Applying to View
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"

    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"

    />

    View Slide

  29. View Slide

  30. Use AppCompat

    View Slide

  31. Use AppCompat
    • Material on all devices
    • Baseline themes/styles
    • Enables View theming pre-Lollipop
    • …And more!

    View Slide

  32. Window Attributes
    
<br/><item name="android:windowBackground">@color/background</item>
<br/><item name="android:statusBarColor">@color/blue_200</item>
<br/><item name="android:windowFullscreen">true</item>
<br/>

    View Slide

  33. Color Attributes
    
<br/><item name="colorPrimary">#F00</item>
<br/><item name="colorPrimaryDark">#0F0</item>
<br/><item name="colorControlNormal">#00F</item>
<br/>

    View Slide

  34. Default Styles
    
<br/><item name="buttonStyle">@style/MyButton</item>
<br/><item name="android:spinnerItemStyle">@style/MySpinnerItem</item>
<br/>
<br/><item name="android:textAppearance">@style/MyText</item>
<br/><item name="android:textAppearanceInverse">@style/MyTextInverse</item>
<br/>

    View Slide

  35. Resource Attributes
    
<br/><item name="selectableItemBackground">@drawable/bg</item>
<br/>


    View Slide

  36. Resource Attributes
    
<br/><item name="selectableItemBackground">@drawable/bg</item>
<br/>


    View Slide

  37. Namespacing
    • Official attributes
    
<br/><item name="android:colorPrimary">#000</item>
<br/>
    • Custom attributes
    
<br/><item name="colorPrimary">#000</item>
<br/>
    v21 only
    appcompat magic

    View Slide

  38. Finding Attributes
    • Most difficult part of themes
    • Anyone can create attributes
    • Anything can use attributes

    View Slide

  39. Attributes in XML
    • Look for ?attr or ?android:attr

    View Slide

  40. Individual Attributes
    • Look for resolveAttribute()
    context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
    attribute

    View Slide

  41. View Style Attributes
    • Look for obtainStyledAttributes()
    TypedArray a = context.obtainStyledAttributes(attrs,

    com.android.internal.R.styleable.ImageView, defStyleAttr, defStyleRes);
    • Investigate TypedArray usage
    int alpha =
    a.getInt(com.android.internal.R.styleable.ImageView_drawableAlpha, 255);
    attribute default

    View Slide

  42. What color is
    what?

    View Slide

  43. Debug Color Theme

    View Slide

  44. Color By
    Numbers
    https://goo.gl/BPNhp1

    View Slide

  45. HierarchyViewer

    View Slide

  46. Dump Theme

    View Slide

  47. Recipe for Sanity
    • Use AppCompat
    • Modify theme first
    • Reference theme attributes
    • Apply themes to Views when necessary
    • Use styles wisely

    View Slide

  48. Resource Qualifiers

    View Slide

  49. 
<br/><item name="android:windowBackground">@color/bg_window</item>
<br/>

    #FF0000



    #0000FF

    View Slide





  50. 
<br/><item name="android:elevation">4dp</item>
<br/>






    
<br/><item name="android:elevation">4dp</item>
<br/>

    View Slide

  51. Qualifier Triangle
    values/Theme values-v21/Theme
    Theme.Used
    qualifier modifications
    what is actually used

    View Slide

  52. Qualifier Diamond
    values/Theme.Platform values-v21/Theme.Platform
    Theme.Platform.Used
    values/Theme attributes for
    everyone
    what is actually used
    qualifier
    modifications

    View Slide

  53. Custom Attributes




    
<br/><item name="myAttribute">4dp</item>
<br/>



    
<br/><item name="android:padding">?attr/myAttribute</item>
<br/>

    View Slide

  54. Custom Attributes




    
<br/><item name="myAttribute">4dp</item>
<br/>



    
<br/><item name="android:padding">?attr/myAttribute</item>
<br/>

    View Slide

  55. Custom Attributes




    
<br/><item name="myAttribute">4dp</item>
<br/>



    
<br/><item name="android:padding">?attr/myAttribute</item>
<br/>

    View Slide

  56. Dynamic Text Appearance
    myTextView.setTextAppearance(context,
    R.style.TextAppearance_AppCompat);

    View Slide

  57. Dynamic Styles
    public View(Context context, AttributeSet attrs,
    int defStyleAttr, int defStyleRes)
    themed context layout attributes
    default style
    (v21+)
    default style attribute
    (from theme, e.g. buttonStyle)

    View Slide

  58. Dynamic Styles
    • Context carries theme
    • ContextThemeWrapper replaces parts of theme
    Context themedContext =
    new ContextThemeWrapper(baseContext, R.style.MyTheme);


    // Use in LayoutInflater

    View view = LayoutInflater.from(themedContext)
    .inflate(R.layout.my_layout, null);


    // Use in View constructor

    View view = new View(themedContext);

    View Slide

  59. Dynamic Theming
    • setTheme()
    • Call before setContentView()
    • Otherwise, restart Activity

    View Slide

  60. Thank You!
    • @danlew42
    • +DanielLew
    • http://danlew.net
    • Color debug theme: https://goo.gl/BPNhp1

    View Slide