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 Slide

  2. segunfamisa
    segunfamisa.com

    View Slide

  3. Introduction

    View Slide

  4. Dark theme was recently introduced in

    View Slide

  5. Why should we care?

    View Slide

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

    View Slide

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

    View 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 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 Slide

  10. View Slide

  11. View Slide

  12. View Slide

  13. View Slide

  14. Key Concepts

    View Slide

  15. Styles & themes

    View Slide

  16. styles

    View Slide

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

    View Slide

  18. 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 Slide

  19. 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 Slide

  20. 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 Slide

  21. themes

    View Slide

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

    View Slide

  23. 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 Slide

  24. 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 Slide

  25. 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 Slide

  26. Themes
    Styles

    View Slide

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

    View Slide

  28. 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 Slide

  29. 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 Slide

  30. Design Systems

    View Slide

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

    View Slide

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

    View Slide

  33. 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 Slide

  34. 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 Slide

  35. Implementing Dark Theme

    View Slide

  36. Simple way

    View Slide

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

    View Slide

  38. Theme colour attributes in Material Design

    View Slide

  39. Theme colour attributes in Material Design

    View Slide

  40. View Slide

  41. colorPrimary
    colorOnPrimary

    View Slide

  42. colorSecondary
    colorOnSecondary

    View Slide

  43. View Slide

  44. Theme typography attributes in Material Design

    View Slide

  45. View Slide

  46. View Slide

  47. View Slide

  48. Understanding attributes

    View Slide

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

    View Slide

  50. 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 Slide



  51. View Slide




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

    View Slide




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

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

    View Slide




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

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

    View Slide




  55. <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 Slide




  56. <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 Slide

  57. View Slide

  58. Fit your design into the material design system

    View Slide

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

    View Slide

  60. 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 Slide

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

    View Slide

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

    View Slide

  63. Colour naming

    View Slide

  64. ..
    Colour naming

    View Slide

  65. ..
    ...
    Colour naming

    View Slide

  66. ..
    ...
    ..
    Colour naming

    View Slide

  67. ..
    ...
    ..
    ..
    Colour naming

    View Slide

  68. ..
    ...
    ..
    ..
    ..
    Colour naming

    View Slide

  69. ..
    ...
    ..
    ..
    ..
    ..
    Colour naming

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  73. View Slide

  74. Putting it all together

    View Slide

  75. Theming with Material Design Components

    View Slide



  76. Theming with Material Design Components

    View Slide



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

    View Slide



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

    View Slide


  79. <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 Slide


  80. <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 Slide


  81. <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 Slide

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

    Theming with Material Design Components
    Theme applied to application

    View Slide

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

    ...

    Theming with Material Design Components
    Theme applied to activity

    View Slide

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

    View Slide

  85. Prefer attributes to direct values

    View Slide

  86. 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 Slide

  87. 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 Slide

  88. 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 Slide

  89. 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 Slide

  90. Handle icons and images

    View Slide

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

    View Slide

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

    View Slide

  93. VectorDrawable

    View Slide

  94. 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 Slide

  95. 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 Slide

  96. VectorDrawable

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

    View Slide

  97. VectorDrawable

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

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

    View Slide

  98. 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 Slide

  99. 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 Slide

  100. 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 Slide

  101. PNG icons

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

    View Slide

  102. PNG icons

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

    View Slide

  103. View Slide

  104. Setting view attributes programmatically

    View Slide

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

    View Slide

  106. 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 Slide

  107. 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 Slide

  108. 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 Slide

  109. 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 Slide

  110. View Slide

  111. Additional tips

    View Slide

  112. Extend Material Design Components with custom attributes
    Additional tips

    View Slide



  113. Extend Material Design Components with custom attributes
    Additional tips

    View Slide




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

    View Slide

  115. Extend Material Design Components with custom attributes
    Additional tips



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

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

    View Slide

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

    View Slide

  117. Takeaways

    View Slide

  118. 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 Slide

  119. Thank you!

    View Slide