Pro Yearly is on sale from $80 to $50! »

Themes, styles & more: from zero to hero

Themes, styles & more: from zero to hero

Haven’t you ever wanted to globally change the appearance of your EditTexts or the font face of all TextViews in your Android application? Themes and styles have always been at the heart of Android development when it comes to UI design. They have been around since API 1 after all and a lot of the Android features are built around them. But do you even know how themes and styles works? What is an attribute? And can you explain the difference between a style, a theme, a text appearance or a theme overlay?

If you have never heard of styles and themes or are not entirely sure you can answer the questions above, this presentation is made for you. This talk will dive deep into the Android styling and theming system. You will learn how to leverage it to customize your Android application, reduce duplication in your code and make your styles cleaner, more manageable and more reusable.

E9bf8f6d5480ea2a2623df7dccfd1f70?s=128

Cyril Mottier

April 23, 2018
Tweet

Transcript

  1. Themes, styles & more From zero to hero @cyrilmottier

  2. None
  3. None
  4. Yes, I’ll talk about boring XML while everybody talks about

    the trendy stuff like Kotlin. “
  5. Yes, I’ll talk about boring XML while everybody talks about

    the trendy stuff like Kotlin. Sorry. “ – The guy talking to you
  6. AAPT 2 \eɪeɪpiːtiː ˈtuː\ AAPT stands for Android Asset Packaging

    Tool. It compiles application resources (e.g. AndroidManifest.xml, XML files, etc.) into binary assets. AAPT also allow clients to view, create, and update Android archives.
  7. The mother of all <style /> A key-value store with

    zero or more pairs
  8. The mother of all <style /> A key-value store with

    zero or more pairs
  9. <style name="ListItem"> <item name="android:minHeight"> @dimen/grid_size_300 </item> </style>

  10. <style name="ListItem"> <item name="android:minHeight"> @dimen/grid_size_300 </item> </style> Style’s name in

    upper camel case name="ListItem"
  11. <style name="ListItem"> <item name="android:minHeight"> @dimen/grid_size_300 </item> </style> Key-value pair <item

    name="android:minHeight"> @dimen/grid_size_300 </item>
  12. <style name="ListItem"> <item name="android:minHeight"> @dimen/grid_size_300 </item> </style> name="android:minHeight" Key

  13. <style name="ListItem"> <item name="android:minHeight"> @dimen/grid_size_300 </item> </style> @dimen/grid_size_300 Value

  14. Keys in styles are called attributes

  15. Carry type information Belong to a namespace Hold optional constraints

    Keys in styles are called attributes
  16. ”any” by default (i.e. when undefined) Attributes Format types

  17. boolean color dimension float string integer enum flags reference fraction

    Attributes Format types
  18. boolean color dimension float string integer enum flags reference fraction

    Resource types Attributes Format types
  19. boolean color dimension float string integer enum flags reference fraction

    Special types Attributes Format types
  20. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" /> Attribute namespace Android framework namespace

  21. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" /> Attribute namespace Android framework namespace

    xmlns:android="http://schemas.android.com/apk/res/android"
  22. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" /> Attribute namespace Android framework namespace

    android android android
  23. Attribute namespace Global namespace schema <TextView xmlns:app="http://schemas.android.com/apk/<your_pkg>" app:layout_constraintTop_toTopOf="parent" />

  24. Attribute namespace Global namespace schema <TextView xmlns:app="http://schemas.android.com/apk/<your_pkg>" app:layout_constraintTop_toTopOf="parent" /> xmlns:app="http://schemas.android.com/apk/<your_pkg>"

    app
  25. Attribute namespace Global namespace schema <TextView xmlns:app="http://schemas.android.com/apk/res-auto" app:layout_constraintTop_toTopOf="parent" /> xmlns:app="http://schemas.android.com/apk/res-auto"

    app
  26. Attribute namespace Global namespace schema <TextView xmlns:app="http://schemas.android.com/apk/res-auto" app:layout_constraintTop_toTopOf="parent" /> xmlns:app="http://schemas.android.com/apk/res-auto"

    Type “appNs” in Android Studio app
  27. <attr name="background" format="reference|color" />

  28. <attr name="background" format="reference|color" /> name="background" Attribute’s name

  29. <attr name="background" format="reference|color" /> Pipe-separated list of types format="reference|color"

  30. <attr name="month" format="integer" min="1" max="12" />

  31. <attr name="month" format="integer" min="1" max="12" /> Upper/lower bounds only with

    integer typed attributes min="1" max="12"
  32. <attr name="layout_width" format="dimension|enum"> <enum name="match_parent" value="-1" /> <enum name="wrap_content" value="-2"

    /> </attr>
  33. Android comes with a bunch of attributes

  34. textColor actionBarStyle windowReturnTransition text src Naming General convention

  35. textColor actionBarStyle windowReturnTransition text src Naming General convention Lower camel

    case
  36. Naming Exc. #1: layout attributes layout_width layout_alignBaseline layout_marginHorizonal layout_weight layout_x

  37. Naming Exc. #1: layout attributes layout_width layout_alignBaseline layout_marginHorizonal layout_weight layout_x

    Prefixed with “layout_” then lower camel case
  38. state_focused state_checked state_enabled state_drag_hovered state_window_focused Naming Exc. #2: state attributes

  39. state_focused state_checked state_enabled state_drag_hovered state_window_focused Naming Exc. #2: state attributes

    Prefixed with “state_” then snake case
  40. Learn the rules like a pro, so you can break

    them like an artist. “ – Pablo Picasso
  41. hand_hour hand_minute ConstraintLayout Readability and ease of use AnalogClock Legacy

    & deprecated layout_constraintGuide_end layout_constraintHeight_max layout_constraintTop_toTopOf
  42. Styles can inherit from each other creating a style hierarchy

  43. <style name="Style.Wars.TheLastJedi" parent="@style/Style.Wars" />

  44. <style name="Style.Wars.TheLastJedi" Explicit parent parent="@ Style.Wars" style/ />

  45. <style name="Style.Wars.TheLastJedi" Explicit parent parent="@Style.Wars" />

  46. Style.Wars" <style name="Style.Wars.TheLastJedi" Explicit parent parent=" />

  47. <style name="Style.Wars.TheLastJedi" />

  48. <style name="Style.Wars.TheLastJedi" /> Implicit parent Style.Wars

  49. <style name="Theme.Card.Nano" parent="android:Theme.Material.Light" />

  50. <style name="Theme.Card.Nano" parent="android:Theme.Material.Light" /> Namespaced parent android:

  51. <style name="Style.Wars.TheLastJedi" parent="" />

  52. <style name="Style.Wars.TheLastJedi" parent="" /> Parentless style parent=""

  53. Shorter is better No parent | Implicit parent | Shorter

    parent form
  54. is a universe of styles Android

  55. Text appearances is a universe of styles Android Themes Theme

    overlays Styles
  56. Style A bag of attributes used to style a View

  57. <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/list_selector" android:minHeight="@dimen/grid_size_400" android:paddingBottom="@dimen/spacing_100"

    android:paddingLeft="@dimen/spacing_200" android:paddingRight="@dimen/spacing_200" android:paddingTop="@dimen/spacing_100" android:text="@string/about" />
  58. <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/list_selector" android:minHeight="@dimen/grid_size_400" android:paddingBottom="@dimen/spacing_100"

    android:paddingLeft="@dimen/spacing_200" android:paddingRight="@dimen/spacing_200" android:paddingTop="@dimen/spacing_100" android:text="@string/about" /> android:background="@drawable/list_selector" android:minHeight="@dimen/grid_size_400" android:paddingBottom="@dimen/spacing_100" android:paddingLeft="@dimen/spacing_200" android:paddingRight="@dimen/spacing_200" android:paddingTop="@dimen/spacing_100"
  59. <style name="ListItem"> <item name="android:background">@drawable/list_selector</item> <item name="android:minHeight">@dimen/grid_size_400</item> <item name="android:paddingBottom">@dimen/spacing_100</item> <item name="android:paddingLeft">@dimen/spacing_200</item>

    <item name="android:paddingRight">@dimen/spacing_200</item> <item name="android:paddingTop">@dimen/spacing_100</item> </style>
  60. <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/list_selector" android:minHeight="@dimen/grid_size_400" android:paddingBottom="@dimen/spacing_100"

    android:paddingLeft="@dimen/spacing_200" android:paddingRight="@dimen/spacing_200" android:paddingTop="@dimen/spacing_100" android:text="@string/about" />
  61. <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/ListItem" android:text="@string/about" />

  62. <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/ListItem" android:text="@string/about" />

  63. <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" style="@style/ListItem" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/about" />

  64. TextAppearance Text styling

  65. <style name="TextAppearance.Title" parent="TextAppearance.AppCompat"> <item name=“android:fontFamily"> @font/museo_sans_rounded_500 </item> <item name="android:textColor">@color/blue_dark</item> <item

    name="android:textSize">@dimen/font_size_large</item> </style>
  66. <style name="TextAppearance.Title" parent="TextAppearance.AppCompat"> <item name=“android:fontFamily"> @font/museo_sans_rounded_500 </item> <item name="android:textColor">@color/blue_dark</item> <item

    name="android:textSize">@dimen/font_size_large</item> </style> TextAppearance. Prefixed by “TextAppearance.”
  67. val tv = findViewById<TextView>(R.id.text) tv.setTextAppearance(R.style.TextAppearance_Title)

  68. val tv = findViewById<TextView>(R.id.text) tv.setTextAppearance(R.style.TextAppearance_Title) Modify TextView’s text appearance tv.setTextAppearance(R.style.TextAppearance_Title)

  69. val spannable = SpannableString("Styles rock!") spannable.setSpan( TextAppearanceSpan(context, R.style.TextAppearance_Title), 0, spannable.length,

    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) textView.text = spannable
  70. val spannable = SpannableString("Styles rock!") spannable.setSpan( TextAppearanceSpan(context, R.style.TextAppearance_Title), 0, spannable.length,

    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) textView.text = spannable TextAppearanceSpan(context, R.style.TextAppearance_Title) Create a Span using the given text appearance
  71. TextAppearance Supported attributes textColor textSize textStyle typeface fontFamily textColorHighlight textColorHint

    textColorLink textAllCaps shadowColor shadowDx shadowDy shadowRadius elegantTextHeight letterSpacing fontFeatureSettings
  72. TextAppearance TextAppearanceSpan attributes textColor textSize textStyle typeface fontFamily textColorHighlight textColorHint

    textColorLink textAllCaps shadowColor shadowDx shadowDy shadowRadius elegantTextHeight letterSpacing fontFeatureSettings
  73. <TextView style="@style/FormHeader" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Title" android:textColor="@color/colorAccent" />

  74. <TextView style="@style/FormHeader" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Title" android:textColor=“@color/blue_cerulean” /> android:textAppearance="@style/TextAppearance.Title" Set TextView’s

    text appearance
  75. <TextView style="@style/FormHeader" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Title" android:textColor="@color/blue_cerulean" /> android:textAppearance="@style/TextAppearance.Title" Least priority

    (applied first)
  76. <TextView style="@style/FormHeader" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Title" android:textColor="@color/blue_cerulean" /> style="@style/FormHeader" Applied then

  77. <TextView style="@style/FormHeader" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.Title" android:textColor="@color/blue_cerulean" /> android:textColor="@color/blue_cerulean" Highest priority

  78. Theme Activity-level styling

  79. Theme Activity-level styling fun Context.setTheme(resId: Int) val Context.theme: Resources.Theme

  80. Theme Activity-level styling fun Context.setTheme(resId: Int) val Context.theme: Resources.Theme fun

    Context.setTheme(resId: Int) Apply the theme to the receiver’s Context
  81. Theme Activity-level styling fun Context.setTheme(resId: Int) val Context.theme: Resources.Theme fun

    Context.setTheme(resId: Int) Must be called before any View is inflated ⚠
  82. <application android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.City"> <!-- ... --> </application>

  83. <application android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.City"> <!-- ... --> </application> android:theme="@style/Theme.City" Application’s

    default theme
  84. <activity android:name=".MainActivity" android:theme="@style/Theme.City.Deluxe" />

  85. <activity android:name=".MainActivity" android:theme="@style/Theme.City.Deluxe" /> Activity specific theme android:theme="@style/Theme.City.Deluxe"

  86. Colors android:colorPrimary android:textColorPrimary

  87. Window configuration android:windowBackground android:windowDisablePreview Colors android:colorPrimary android:textColorPrimary

  88. Window configuration android:windowBackground android:windowDisablePreview Colors android:colorPrimary android:textColorPrimary Default widget styles

    android:textViewStyle android:progressBarStyle
  89. Window configuration android:windowBackground android:windowDisablePreview Colors android:colorPrimary android:textColorPrimary Default widget styles

    android:textViewStyle android:progressBarStyle Drawables android:selectableItemBackground android:listDivider
  90. Drawables android:selectableItemBackground android:listDivider Preferences styles android:switchPreferenceStyle android:editTextPreferenceStyle Window configuration android:windowBackground

    android:windowDisablePreview Colors android:colorPrimary android:textColorPrimary Default widget styles android:textViewStyle android:progressBarStyle
  91. Text appearances android:textAppearanceSmall android:textAppearanceLargeInverse Preferences styles android:switchPreferenceStyle android:editTextPreferenceStyle Drawables android:selectableItemBackground

    android:listDivider Window configuration android:windowBackground android:windowDisablePreview Colors android:colorPrimary android:textColorPrimary Default widget styles android:textViewStyle android:progressBarStyle
  92. Text appearances android:textAppearanceSmall android:textAppearanceLargeInverse Preferences styles android:switchPreferenceStyle android:editTextPreferenceStyle Misc. android:dialogTheme

    android:disabledAlpha Drawables android:selectableItemBackground android:listDivider Window configuration android:windowBackground android:windowDisablePreview Colors android:colorPrimary android:textColorPrimary Default widget styles android:textViewStyle android:progressBarStyle
  93. Theme attributes can be referenced in layouts, styles, etc.

  94. <style name="ListItem"> <item name=“android:background”> @drawable/list_selector </item> <item name="android:minHeight">@dimen/grid_size_400</item> <item name="android:paddingBottom">@dimen/spacing_100</item>

    <item name="android:paddingLeft">@dimen/spacing_200</item> <item name="android:paddingRight">@dimen/spacing_200</item> <item name="android:paddingTop">@dimen/spacing_100</item> </style>
  95. <style name="ListItem"> <item name=“android:background”> ?android:attr/selectableItemBackground </item> <item name="android:minHeight">@dimen/grid_size_400</item> <item name="android:paddingBottom">@dimen/spacing_100</item>

    <item name="android:paddingLeft">@dimen/spacing_200</item> <item name="android:paddingRight">@dimen/spacing_200</item> <item name="android:paddingTop">@dimen/spacing_100</item> </style>
  96. ?android:attr/selectableItemBackground

  97. Indicates a theme lookup ?android:attr/selectableItemBackground ?

  98. Theme attribute namespace ?android:attr/selectableItemBackground android:

  99. Attribute lookup ?android:attr/selectableItemBackground attr/

  100. Theme attribute actual name ?android:attr/selectableItemBackground selectableItemBackground

  101. ?android:selectableItemBackground

  102. ?colorPrimary

  103. fun Context.obtainStyledAttributes( set: AttributeSet, attrs: IntArray, defStyleAttr: Int, defStyleRes: Int

    ): TypedArray How it works Theming is not so magical after all…
  104. None
  105. Theme overlays View-level theming

  106. <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:theme="@style/ThemeOverlay.Bazinga"> <!-- ... --> </LinearLayout>

  107. <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:theme="@style/ThemeOverlay.Bazinga"> <!-- ... --> </LinearLayout> Override

    the current theme with the given theme overlay android:theme="@style/ThemeOverlay.Bazinga"
  108. Few notes about theme overlays Based on ContextThemeWrapper A bag

    of theme attributes Propagated to descendants
  109. Compatibility Theming on different API levels

  110. with AppCompat Theme overlays API 21 API 14 API 23

  111. with AppCompat Theme overlays Theme attributes API 21 API 14

    API 23
  112. with AppCompat Theme overlays Theme attributes in layout & styles

    API 21 API 14 API 23
  113. with AppCompat Theme overlays Theme attributes in layout & styles

    in Drawables API 21 API 14 VD & AVD only API 23
  114. with AppCompat Theme overlays Theme attributes in layout & styles

    in Drawables in ColorStateList API 21 API 14 with AppCompat with AppCompat VD & AVD only API 23
  115. Theming & tinting in the real life

  116. None
  117. None
  118. None
  119. None
  120. layout/list_item_user.xml <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.XXH1" android:textColor="?zenlyListItemTextColorPrimary" /> <TextView android:id="@+id/subtitle"

    android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.XH3" android:textColor="?zenlyListItemTextColorSecondary" />
  121. layout/list_item_user.xml <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.XXH1" android:textColor="?zenlyListItemTextColorPrimary" /> <TextView android:id="@+id/subtitle"

    android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.XH3" android:textColor="?zenlyListItemTextColorSecondary" /> android:textColor="?zenlyListItemTextColorPrimary" android:textColor="?zenlyListItemTextColorSecondary"
  122. <android.support.v7.widget.AppCompatImageView android:id="@+id/search_icon" android:layout_width="@dimen/grid_size_350" android:layout_height="@dimen/grid_size_350" android:background="?selectableItemBackgroundBorderless" android:scaleType="centerInside" android:src="@drawable/ic_search" app:tint="?colorControlNormal" /> layout/fragment_dashboard.xml

  123. <android.support.v7.widget.AppCompatImageView android:id="@+id/search_icon" android:layout_width="@dimen/grid_size_350" android:layout_height="@dimen/grid_size_350" android:background="?selectableItemBackgroundBorderless" android:scaleType="centerInside" android:src="@drawable/ic_search" app:tint="?colorControlNormal" /> layout/fragment_dashboard.xml

    android:background="?selectableItemBackgroundBorderless" app:tint="?colorControlNormal" />
  124. values/themes.xml values/theme_overlays.xml <style name="Theme.Zenly" parent="Base.Theme.Zenly"> <item name=“colorControlNormal"> @color/blue_dark </item> <item

    name=“zenlyListItemTextColorPrimary"> @color/white </item> <item name=“zenlyListItemTextColorSecondary"> @color/blue_heavy </item> <item name=“android:listDivider"> @drawable/divider_blue_medium </item> </style> <style name="ThemeOverlay.Zenly.Light"> <item name="colorControlNormal"> @color/gray_medium </item> <item name="zenlyListItemTextColorPrimary"> @color/blue_dark </item> <item name="zenlyListItemTextColorSecondary"> @color/gray_medium </item> <item name="android:listDivider"> @drawable/divider_gray_light </item> </style>
  125. <style name="ThemeOverlay.Zenly.Light"> <item name="colorControlNormal"> @color/gray_medium </item> <item name="zenlyListItemTextColorPrimary"> @color/blue_dark </item>

    <item name="zenlyListItemTextColorSecondary"> @color/gray_medium </item> <item name="android:listDivider"> @drawable/divider_gray_light </item> </style> values/themes.xml values/theme_overlays.xml <style name="Theme.Zenly" parent="Base.Theme.Zenly"> <item name=“colorControlNormal"> @color/blue_dark </item> <item name=“zenlyListItemTextColorPrimary"> @color/white </item> <item name=“zenlyListItemTextColorSecondary"> @color/blue_heavy </item> <item name=“android:listDivider"> @drawable/divider_blue_medium </item> </style> @color/gray_medium @color/blue_dark @color/gray_medium @drawable/divider_gray_light @color/blue_dark @color/white @color/blue_heavy @drawable/divider_blue_medium
  126. <FrameLayout android:id="@+id/dashboard_bottom_sheet" android:layout_width="match_parent" android:layout_height="match_parent" android:theme="@style/ThemeOverlay.Zenly.Light" app:behavior_hideable="true" app:behavior_peekHeight="360dp" app:layout_behavior="android.support.design.widget.BottomSheetBehavior"> <!-- ...

    --> </FrameLayout> layout/fragment_dashboard.xml
  127. <FrameLayout android:id="@+id/dashboard_bottom_sheet" android:layout_width="match_parent" android:layout_height="match_parent" android:theme="@style/ThemeOverlay.Zenly.Light" app:behavior_hideable="true" app:behavior_peekHeight="360dp" app:layout_behavior="android.support.design.widget.BottomSheetBehavior"> <!-- ...

    --> </FrameLayout> layout/fragment_dashboard.xml android:theme="@style/ThemeOverlay.Zenly.Light"
  128. None
  129. Normal mode Night mode

  130. values/themes.xml <style name="Theme.Zenly" parent="Base.Theme.Zenly"> <item name="colorPrimary">@color/blue</item> <item name="colorPrimaryDark">@color/blue_dark</item> <item name="colorAccent">@color/green</item>

    <item name="colorControlNormal">@color/blue_dark</item> <item name="zenlyColorBackground">@color/blue</item> <item name="zenlyListItemTextColorPrimary">@color/white</item> <item name="zenlyListItemTextColorSecondary">@color/blue_heavy</item> <!-- ... --> </style>
  131. values-night/themes.xml <style name="Theme.Zenly" parent="Base.Theme.Zenly"> <item name="colorPrimary">@color/blue_dark</item> <item name="colorPrimaryDark">@color/blue_black</item> <item name="colorAccent">@color/green</item>

    <item name="colorControlNormal">@color/blue_heavy</item> <item name="zenlyColorBackground">@color/blue_dark</item> <item name="zenlyListItemTextColorPrimary">@color/white</item> <item name="zenlyListItemTextColorSecondary">@color/white_o50</item> <!-- ... --> </style>
  132. @Override protected void onCreate(@Nullable Bundle savedInstanceState) { final int uiMode

    = AppPrefs.from(this).getUiMode(); if (uiMode == AppPrefs.UI_MODE_NIGHT) { getDelegate().setLocalNightMode( AppCompatDelegate.MODE_NIGHT_YES); } else { getDelegate().setLocalNightMode( AppCompatDelegate.MODE_NIGHT_NO); } super.onCreate(savedInstanceState); // ... }
  133. Organizing styles Good practices for XML clean architecture

  134. <style name="Theme.City" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:navigationBarColor">@color/black_o30</item> <item name="android:statusBarColor">@color/black_o30</item> <item name="android:windowBackground">@color/white</item> <item

    name="android:windowTranslucentNavigation">true</item> </style> values/themes.xml
  135. <style name="Theme.City" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:navigationBarColor">@color/black_o30</item> <item name="android:statusBarColor">@color/black_o30</item> <item name="android:windowBackground">@color/white</item> <item

    name="android:windowTranslucentNavigation">true</item> </style> <item name="android:navigationBarColor">@color/black_o30</item> <item name="android:statusBarColor">@color/black_o30</item> <item name="android:windowTranslucentNavigation">true</item> values/themes.xml Lint warnings
  136. <style name="Theme.City" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@color/white</item> </style> values/themes.xml <style name="Theme.City" parent="Theme.AppCompat.Light.NoActionBar">

    <item name="android:navigationBarColor">@color/black_o30</item> <item name="android:statusBarColor">@color/black_o30</item> <item name="android:windowBackground">@color/white</item> <item name="android:windowTranslucentNavigation">true</item> </style> values-v21/themes.xml
  137. <style name="Theme.City" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@color/white</item> </style> values/themes.xml <style name="Theme.City" parent="Theme.AppCompat.Light.NoActionBar">

    <item name="android:navigationBarColor">@color/black_o30</item> <item name="android:statusBarColor">@color/black_o30</item> <item name="android:windowBackground">@color/white</item> <item name="android:windowTranslucentNavigation">true</item> </style> parent="Theme.AppCompat.Light.NoActionBar" parent="Theme.AppCompat.Light.NoActionBar" Parent style duplication values-v21/themes.xml
  138. <style name="Theme.City" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@color/white</item> </style> values/themes.xml <style name="Theme.City" parent="Theme.AppCompat.Light.NoActionBar">

    <item name="android:navigationBarColor">@color/black_o30</item> <item name="android:statusBarColor">@color/black_o30</item> <item name="android:windowBackground">@color/white</item> <item name="android:windowTranslucentNavigation">true</item> </style> Items duplication <item name="android:windowBackground">@color/white</item> <item name="android:windowBackground">@color/white</item> values-v21/themes.xml
  139. Theme.City values values-v21 values-v23 Base.Theme.City Base.Theme.City Base.Theme.City Base.V23.Theme.City Base.V21.Theme.City Base.V1.Theme.City

  140. Theme.City values values-v21 values-v23 Base.Theme.City Base.Theme.City Base.Theme.City Base.V23.Theme.City Base.V21.Theme.City Base.V1.Theme.City

  141. Theme.City values values-v21 values-v23 Base.Theme.City Base.Theme.City Base.Theme.City Base.V23.Theme.City Base.V21.Theme.City Base.V1.Theme.City

  142. Theme.City values values-v21 values-v23 Base.Theme.City Base.Theme.City Base.Theme.City Base.V23.Theme.City Base.V21.Theme.City Base.V1.Theme.City

  143. Theme.City values values-v21 values-v23 Base.Theme.City Base.Theme.City Base.Theme.City Base.V23.Theme.City Base.V21.Theme.City Base.V1.Theme.City

  144. Theme.City values values-v21 values-v23 Base.Theme.City Base.Theme.City Base.Theme.City Base.V23.Theme.City Base.V21.Theme.City Base.V1.Theme.City

    on API 22
  145. Theme.City values values-v21 values-v23 Base.Theme.City Base.Theme.City Base.Theme.City Base.V23.Theme.City Base.V21.Theme.City Base.V1.Theme.City

    on API 26
  146. values/themes_base.xml <style name="Base.V1.Theme.City" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@color/white</item> </style> <style name="Base.Theme.City" parent="Base.V1.Theme.City"

    />
  147. <style name="Base.V21.Theme.City" parent="Base.V1.Theme.City"> <item name="android:navigationBarColor">@color/black_o30</item> <item name="android:statusBarColor">@color/black_o30</item> <item name="android:windowTranslucentNavigation">true</item> </style>

    <style name="Base.Theme.City" parent="Base.V21.Theme.City" /> values-v21/themes_base.xml
  148. values/themes.xml <style name="Theme.City" parent="Base.Theme.City" />

  149. Prefix Filename text_appearances.xml themes.xml theme_overlays.xml TextAppearance. Theme. ThemeOverlay. Text appearances

    Themes Theme overlays styles_widget.xml Widget. Widget styles styles.xml - Custom styles
  150. Prefix Filename text_appearances_base.xml themes_base.xml theme_overlays_base.xml Base.TextAppearance. Base.Theme. Base.ThemeOverlay. Base text

    appearances Base themes Base theme overlays styles_widget_base.xml Base.Widget. Base widget styles styles_base.xml Base. Base custom styles
  151. Thank you! @cyrilmottier cyrilmottier.com