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

Leveraging themes and styles to implement dark mode on Android

Leveraging themes and styles to implement dark mode on Android

Presentation at DevFest Nürnberg, 2019 (https://devfestnuremberg.com/)

Abstract:
In recent times, light and dark modes have become popular in apps and as a result, users are starting to expect this feature in the apps they use.

In Android 10, users are now able to set their device theme to dark or light. In order to be able to deliver a consistent experience for users across many apps, it’s good for these apps to respond appropriately to the theme set by the user on their device.

In order to implement this feature in our apps, there are changes we need to make to our app.

In this talk, we will look at how we can collaborate with our designers and support this feature in our apps. We will cover topics ranging from adopting a design system, to leveraging material design components, making use of styles and themes, the process of migration from no-design-system to using a design system.

By the end of this talk, we would have covered in practical steps, what we need and how to go about supporting dark mode in our apps in incremental steps.

Resources & Links in the presentation
* Android Dev Summit, 2019: https://youtu.be/Owkf8DhAOSo?t=168
* “Consistency is Key - Working with a Design System” - Maria Neumayer - https://www.youtube.com/watch?v=THYqC3ACadQ
* Material Design Components on GitHub: https://github.com/material-components/material-components-android
* https://jorgecastillo.dev/dependency-inversion-on-android-theming
* https://material.io/develop/android/theming/color/

Segun Famisa

December 14, 2019
Tweet

More Decks by Segun Famisa

Other Decks in Programming

Transcript

  1. Light or Dark
    using themes and styles to
    implement “dark mode” on Android

    View full-size slide

  2. segunfamisa
    segunfamisa.com

    View full-size slide

  3. Introduction

    View full-size slide

  4. Dark theme was recently introduced in

    View full-size slide

  5. Why should we care?

    View full-size slide

  6. Why should we care?
    Can reduce power usage on some devices

    View full-size slide

  7. Why should we care?
    Can reduce power usage on some devices
    Gentle on the eyes in low-light conditions

    View full-size slide

  8. Why should we care?
    Can reduce power usage on some devices
    Gentle on the eyes in low-light conditions
    More and more apps are supporting it

    View full-size slide

  9. Why should we care?
    Can reduce power usage on some devices
    Gentle on the eyes in low-light conditions
    More and more apps are supporting it
    Users will soon start to expect it in your
    app

    View full-size slide

  10. Key Concepts

    View full-size slide

  11. Styles & themes

    View full-size slide

  12. styles
    “map of View attributes to values”
    - Nick Butcher (Android Dev Summit 2019)
    https://youtu.be/Owkf8DhAOSo?t=168

    View full-size slide

  13. styles.xml

    <br/><item name="android:textColor">@color/text_color_gray</item><br/><item name="android:textSize">@dimen/normal_text</item><br/>...<br/><item name="android:maxLines">1</item><br/>

    View full-size slide

  14. styles.xml

    <br/><item name="android:textColor">@color/text_color_gray</item><br/><item name="android:textSize">@dimen/normal_text</item><br/>...<br/><item name="android:maxLines">1</item><br/>
    View attributes

    View full-size slide

  15. styles.xml

    <br/><item name="android:textColor">@color/text_color_gray</item><br/><item name="android:textSize">@dimen/normal_text</item><br/>...<br/><item name="android:maxLines">1</item><br/>
    Values

    View full-size slide

  16. themes
    “map of theme attributes to values”
    - Nick Butcher (Android Dev Summit 2019)
    https://youtu.be/Owkf8DhAOSo?t=168

    View full-size slide

  17. themes
    <br/><item name="colorPrimary">@color/colorPrimary</item><br/><item name="colorPrimaryDark">@color/colorPrimaryDark</item><br/>...<br/><item name="colorAccent">@color/colorAccent</item><br/>

    View full-size slide

  18. themes
    <br/><item name="colorPrimary">@color/colorPrimary</item><br/><item name="colorPrimaryDark">@color/colorPrimaryDark</item><br/>...<br/><item name="colorAccent">@color/colorAccent</item><br/>
    theme attributes

    View full-size slide

  19. themes
    <br/><item name="colorPrimary">@color/colorPrimary</item><br/><item name="colorPrimaryDark">@color/colorPrimaryDark</item><br/>...<br/><item name="colorAccent">@color/colorAccent</item><br/>
    Values

    View full-size slide

  20. Themes
    Styles

    View full-size slide

  21. Themes
    Styles
    Collection of attributes that
    specify the appearance for a
    single View

    View full-size slide

  22. Themes
    Collection of attributes
    applied to an entire app,
    activity, or view
    hierarchy—not just an
    individual view
    Styles
    Collection of attributes that
    specify the appearance for a
    single View

    View full-size slide

  23. Themes
    Collection of attributes
    applied to an entire app,
    activity, or view
    hierarchy—not just an
    individual view
    ViewGroups pass down themes
    to their descendants
    Styles
    Collection of attributes that
    specify the appearance for a
    single View

    View full-size slide

  24. Design Systems

    View full-size slide

  25. A design system helps to scale designs by making reusable
    components, widgets, and styles.

    View full-size slide

  26. A design system helps to scale designs by making reusable
    components, widgets, and styles.
    “Design systems” is a whole topic on its own.

    View full-size slide

  27. A design system helps to scale designs by making reusable
    components, widgets, and styles.
    “Design systems” is a whole topic on its own.
    “Consistency is Key - Working with a Design System”
    - Maria Neumayer, Deliveroo
    https://www.youtube.com/watch?v=THYqC3ACadQ

    View full-size slide

  28. A design system helps to scale designs by making reusable
    components, widgets, and styles.
    “Design systems” is a whole topic on its own.
    “Consistency is Key - Working with a Design System”
    - Maria Neumayer, Deliveroo
    https://www.youtube.com/watch?v=THYqC3ACadQ
    Material Design is a design system too

    View full-size slide

  29. Implementing Dark Theme

    View full-size slide

  30. Material Design Components
    https://github.com/material-components/material-components-android

    View full-size slide

  31. Theme colour attributes in Material Design

    View full-size slide

  32. Theme colour attributes in Material Design

    View full-size slide

  33. colorPrimary
    colorOnPrimary

    View full-size slide

  34. colorSecondary
    colorOnSecondary

    View full-size slide

  35. Theme typography attributes in Material Design

    View full-size slide

  36. Understanding attributes

    View full-size slide

  37. Attributes are like interfaces, and the referenced colours
    are like implementations.
    Understanding attributes

    View full-size slide

  38. Attributes are like interfaces, and the referenced colours
    are like implementations.
    Allows for inversion of control. Only change the
    implementations to change the value.
    https://jorgecastillo.dev/dependency-inversion-on-android-theming
    Understanding attributes

    View full-size slide




  39. <br/><item name="colorSurface">@color/white</item><br/><item name="colorOnSurface">@color/blue_500</item><br/>

    View full-size slide




  40. <br/><item name="colorSurface">@color/white</item><br/><item name="colorOnSurface">@color/blue_500</item><br/>

    ...
    android:textColor="?attr/colorOnSurface"/>

    View full-size slide




  41. <br/><item name="colorSurface">@color/white</item><br/><item name="colorOnSurface">@color/blue_500</item><br/>

    ...
    android:textColor="?attr/colorOnSurface"/>

    View full-size slide




  42. <br/><item name="colorSurface">@color/white</item><br/><item name="colorOnSurface">@color/blue_500</item><br/>

    ...
    android:textColor="?attr/colorOnSurface"/>



    <br/><item name="colorSurface">@color/black</item><br/><item name="colorOnSurface">@color/red_500</item><br/>

    ...
    android:textColor="?attr/colorOnSurface"/>

    View full-size slide




  43. <br/><item name="colorSurface">@color/white</item><br/><item name="colorOnSurface">@color/blue_500</item><br/>

    ...
    android:textColor="?attr/colorOnSurface"/>



    <br/><item name="colorSurface">@color/black</item><br/><item name="colorOnSurface">@color/red_500</item><br/>

    ...
    android:textColor="?attr/colorOnSurface"/>

    View full-size slide

  44. Fit your design into the material design system

    View full-size slide

  45. Look at how you can fit your design into existing material
    design system framework
    Fit your design into the material design system

    View full-size slide

  46. Look at how you can fit your design into existing material
    design system framework
    Identify what could be the colorPrimary, colorSecondary,
    colorOnPrimary, etc.
    Fit your design into the material design system

    View full-size slide

  47. https://material.io/develop/android/theming/color/

    View full-size slide

  48. https://material.io/develop/android/theming/color/

    View full-size slide

  49. Colour naming

    View full-size slide

  50. ..
    Colour naming

    View full-size slide

  51. ..
    ...
    Colour naming

    View full-size slide

  52. ..
    ...
    ..
    Colour naming

    View full-size slide

  53. ..
    ...
    ..
    ..
    Colour naming

    View full-size slide

  54. ..
    ...
    ..
    ..
    ..
    Colour naming

    View full-size slide

  55. ..
    ...
    ..
    ..
    ..
    ..
    Colour naming

    View full-size slide

  56. Instead, it’s recommended to name your colours by shade

    View full-size slide

  57. Instead, it’s recommended to name your colours by shade
    ..
    ...
    ..
    ..
    ..
    ..

    View full-size slide

  58. Instead, it’s recommended to name your colours by shade
    ..
    ...
    ..
    ..
    ..
    ..

    View full-size slide

  59. Putting it all together

    View full-size slide

  60. Theming with Material Design Components

    View full-size slide



  61. Theming with Material Design Components

    View full-size slide



  62. Theming with Material Design Components
    Make your theme extend DayNight from MDC

    View full-size slide



  63. Theming with Material Design Components
    Bridge: inherits from AppCompat and still brings new
    attributes from MDC

    View full-size slide


  64. <br/><item name="colorPrimary">@color/main_blue_500</item><br/><item name="colorPrimaryVariant">@color/main_blue_300</item><br/><item name="colorSecondary">@color/main_red_500</item><br/><item name="colorSecondaryVariant">@color/main_red_300</item><br/>...<br/><item name="colorOnPrimary">@color/white</item><br/>
    Theming with Material Design Components

    View full-size slide


  65. <br/><item name="colorPrimary">@color/main_blue_300</item><br/><item name="colorPrimaryVariant">@color/main_blue_500</item><br/><item name="colorSecondary">@color/main_red_300</item><br/><item name="colorSecondaryVariant">@color/main_red_500</item><br/>...<br/><item name="colorOnPrimary">@color/white</item><br/>
    Theming with Material Design Components

    View full-size slide


  66. <br/><item name="colorPrimary">...</item><br/><item name="colorPrimaryVariant">...</item><br/><item name="colorSecondary">...</item><br/><item name="colorSecondaryVariant">...</item><br/>...<br/><item name="colorOnPrimary">...</item><br/>

    <br/><item name="colorPrimary">...</item><br/><item name="colorPrimaryVariant">...</item><br/><item name="colorSecondary">...</item><br/><item name="colorSecondaryVariant">...</item><br/>...<br/><item name="colorOnPrimary">...</item><br/>

    View full-size slide

  67. ...
    android:theme="@style/MyTheme">
    ...
    ...

    Theming with Material Design Components
    Theme applied to application

    View full-size slide

  68. ...
    ...
    android:theme="@style/MyAppTheme.Special">
    ...

    ...

    Theming with Material Design Components
    Theme applied to activity

    View full-size slide

  69. application
    colorPrimary
    activity
    ViewGroup/View
    @style/Theme.Blue
    @style/Theme.Green
    @style/Theme.Red

    View full-size slide

  70. Prefer attributes to direct values

    View full-size slide

  71. Prefer attributes to direct values
    android:id="@+id/article_source_text"
    ...
    android:textColor="@color/light_grey"/>
    android:id="@+id/article_title"
    ...
    android:textColor="@color/dark_blue/>
    android:id="@+id/article_description"
    ...
    android:textColor="@color/light_grey"/>

    View full-size slide

  72. Prefer attributes to direct values
    android:id="@+id/article_source_text"
    ...
    android:textColor="@color/light_grey"/>
    android:id="@+id/article_title"
    ...
    android:textColor="@color/dark_blue/>
    android:id="@+id/article_description"
    ...
    android:textColor="@color/light_grey"/>
    We can’t easily create a night mode equivalent
    with these direct values

    View full-size slide

  73. android:id="@+id/article_source_text"
    ...
    android:textColor="?android:attr/textColorPrimary"/>
    android:id="@+id/article_title"
    ...
    android:textColor="?attr/colorOnSurface/>
    android:id="@+id/article_description"
    ...
    android:textColor="?android:attr/textColorSecondary"/>
    Prefer attributes to direct values

    View full-size slide

  74. android:id="@+id/article_source_text"
    ...
    android:textColor="?android:attr/textColorPrimary"/>
    android:id="@+id/article_title"
    ...
    android:textColor="?attr/colorOnSurface”/>
    android:id="@+id/article_description"
    ...
    android:textColor="?android:attr/textColorSecondary"/>
    Prefer attributes to direct values

    View full-size slide

  75. Handle icons and images

    View full-size slide

  76. Handle icons and images
    res
    ├── drawable
    │ ├── ...
    │ └── ic_back.png
    └── drawable-night
    ├── ...
    └── ic_back.png

    View full-size slide

  77. Handle icons and images
    res
    ├── drawable
    │ ├── ...
    │ └── ic_back.png
    └── drawable-night
    ├── ...
    └── ic_back.png

    View full-size slide

  78. VectorDrawable

    View full-size slide

  79. VectorDrawable
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    android:fillColor="#FF000000"
    android:pathData="M20,11H7.8...-2z"/>

    light dark

    View full-size slide

  80. VectorDrawable
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    android:fillColor="#FF000000"
    android:pathData="M20,11H7.8...-2z"/>

    light dark

    View full-size slide

  81. VectorDrawable

    <br/>...<br/><item name="colorOnPrimary">@color/black</item><br/>

    View full-size slide

  82. VectorDrawable

    <br/>...<br/><item name="colorOnPrimary">@color/black</item><br/>

    <br/>...<br/><item name="colorOnPrimary">@color/white</item><br/>

    View full-size slide

  83. VectorDrawable
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    android:fillColor="?attr/colorOnPrimary"
    android:pathData="M20,11H7.8...-2z"/>

    View full-size slide

  84. VectorDrawable
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    android:fillColor="?attr/colorOnPrimary"
    android:pathData="M20,11H7.8...-2z"/>

    View full-size slide

  85. VectorDrawable
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
    android:fillColor="?attr/colorOnPrimary"
    android:pathData="M20,11H7.8...-2z"/>

    light dark

    View full-size slide

  86. PNG icons

    android:src="@drawable/ic_arrow_back"
    ...
    app:tint="?attr/colorOnPrimary"/>

    View full-size slide

  87. PNG icons

    android:src="@drawable/ic_arrow_back"
    ...
    app:tint="?attr/colorOnPrimary"/>

    View full-size slide

  88. Setting view attributes programmatically

    View full-size slide

  89. val textColor = ContextCompat.getColor(this, R.color.color_black)
    titleView.setTextColor(textColor)
    Setting view attributes programmatically

    View full-size slide

  90. Setting view attributes programmatically
    val textColor = ContextCompat.getColor(this, R.color.color_black)
    titleView.setTextColor(textColor)
    val textColor = getAttributeColor(R.attr.colorOnPrimary)
    titleView.setTextColor(textColor)

    View full-size slide

  91. val textColor = ContextCompat.getColor(this, R.color.color_black)
    titleView.setTextColor(textColor)
    val textColor = getColorAttribute(R.attr.colorOnPrimary)
    titleView.setTextColor(textColor)
    Setting view attributes programmatically

    View full-size slide

  92. Setting view attributes programmatically
    val textColor = getColorAttribute(R.attr.colorOnPrimary)
    ...
    @ColorInt
    fun Context.getColorAttribute(@AttrRes attr: Int): Int {
    return obtainStyledAttributes(intArrayOf(attr))
    .use {
    it.getColor(0, Color.RED)
    }
    }

    View full-size slide

  93. Setting view attributes programmatically
    val textColor = getColorAttribute(R.attr.colorOnPrimary)
    ...
    @ColorInt
    fun Context.getColorAttribute(@AttrRes attr: Int): Int {
    return obtainStyledAttributes(intArrayOf(attr))
    .use {
    it.getColor(0, Color.RED)
    }
    }
    Android Annotations:
    Lint warning when we pass a different kind of
    “integer”

    View full-size slide

  94. Additional tips

    View full-size slide

  95. Extend Material Design Components with custom attributes
    Additional tips

    View full-size slide



  96. Extend Material Design Components with custom attributes
    Additional tips

    View full-size slide




  97. <br/><item name="specialAccentColor">@color/main_blue_350</item><br/>
    Extend Material Design Components with custom attributes
    Additional tips

    View full-size slide

  98. Extend Material Design Components with custom attributes
    Additional tips



    <br/><item name="specialAccentColor">@color/main_blue_350</item><br/>

    ...
    android:textColor="?attr/specialAccentColor"/>

    View full-size slide

  99. Extend Material Design Components with custom attributes
    Use AppCompatDelegate for compatibility with old versions of
    android
    Additional tips

    View full-size slide

  100. Takeaways
    ● Be careful of which context you use
    ● Styles are for single views, and themes are for multiple
    views or activities or for the application
    ● Prefer using attributes over direct reference to values -
    esp. Colours
    ● Get familiar with attributes from MDC library
    ● Use AVDs for icons when possible

    View full-size slide