In order to increase the user traffic of the android application, there is a need of tweaking the Theme and the Style of the android application. In today’s mobile application development one also need to consider the look and feel of the application. One major feature in the application user needs is the Dark Theme. The default theme for the Android devices was dark until Android lollipop(5.0) but the Android Q released in the 3rd quarter of 2019. The majority of the applications implemented their dark theme version of the application. In this article, it’s been illustrated how to implement the Material Dark theme version of the Android Application.
Why Dark Theme?
Dark themes reduce the luminance emitted by mobile device screens, hence reducing eye strain. Also maintaining the minimum color contrast. This also helps in the functional design of the application. Consuming less battery power, adjusting to the current condition of light. Devices with OLED displays can get befit of the Dark themes. Most importantly, there are more fans for the Dark theme version of the application.
Understanding the difference between styles and themes
- Android developers witness the ambiguity in styles and themes. The reason is that in Android there are only tag names <style>, there is no <theme> tag available.
- Style is a collection of attributes that define the appearance of a single view. The style attributes are the font, color, size, background color, etc. For example, the font size may be different for heading and body.
- Theme, on the contrary, is applied to the entire app, or activity, or view hierarchy, not just for individual views. Themes can also apply styles to non-view elements such as status bar, window background, etc. For example, the colorPrimary is applied to all the Floating Action Buttons or Normal Buttons of the entire application. One can get the difference in the following image.
- The above image clearly can see the difference between, The Styles and the Theme. Where the style is applied for the particular view inside the parent View group, but the theme is applied to the entire parent view group.
- But Styles and Themes go hand in hand For Example the Floating Action Button and Normal clickable buttons can have different colors like colorPrimary, and colorSecondary respectively.
Material Theming Properties
The Main 3 properties to achieve functional material theme in Android application are:
- Color
- Typography
- Shape
- Material Design Components
- One can get the basic information about these properties can refer to Introduction to Material Design in Android
- One may have seen in the recent update of Android studio (4.1 and above) The Color properties are made different. Those are:
Primary Color Variants:
Attribute |
Description |
Default Value |
---|---|---|
colorPrimary | This color primary color of the application. This color is the most used color in the Application. This can also be called a branding color | #FF6200EE |
colorPrimaryVariant | This is the variant of the colorPrimary. This may be a lighter or darker variant of the primary color. | #FF3700B3 |
colorOnPrimary | The name itself indicates the color should be assigned to those elements which are above the colorPrimary. | #FFFFFFFF |
Secondary Color Variants:
Attribute |
Description |
Default Value |
---|---|---|
colorSecondary | The color which is most used after the colorPrimary. This color is accented complement color of the colorPrimary. | #FF03DAC5 |
colorSecondaryVariant | This is a variant of the colorSecondary. This may be a lighter or darker variant of the colorSecondary. | #FF018786 |
colorOnSecondary | This name also indicates that the color should be assigned to those elements which are above the colorSecondary. | #FF000000 |
Surface Colors:
Attribute |
Description |
Default Value |
---|---|---|
colorSurface | Surface color that affects surface components, such as cards, sheets, menus. | #FFFFFF |
colorOnSurface | This color assigned to the texts or icons which are above the colorSurface | #000000 |
Colors for Errors:
Attribute | Description | Default Value |
---|---|---|
colorError | This indicated the color assigned to elements which state, the error. | #B00020 |
colorOnError | The color which is assigned to texts or icons which are above the colorError. | #FFFFFF |
Typography:
There are predefined and well-engineered typography variants of the text in the Material Design Typography system. Have look at the following image:
These are by default are the attributes that come with the Material Design theme, and can be applied directly to the TextViews according to the context of the Text in the application.
Steps to implement the Dark Theme variant of the Application
Step 1: Create empty activity Android Studio project:
Create an empty activity Android Studio project and select Kotlin as the programming language. Refer to Android | How to Create/Start a New Project in Android Studio?.
Step 2: Add the required dependency
- Add the following dependency to the app-level gradle file, and sync the project.
- This dependency, however, is added by default when the new Android Studio(version 4.0 and above) project is created.
implementation ‘com.google.android.material:material:1.3.0-alpha04’
Step 3: Adding the Primary and Secondary brand colors
- We need to primarily decide the Primary and Secondary color, and take the color code out of it. In this case, The Primary Color is green and complement to it there is red_200 and red_700 as Secondary brand colors.
- One can make their own color swatches and combination using either this or this.
- Invoke the following colors to implement the same in the application inside the colors.xml file.
<? xml version = "1.0" encoding = "utf-8" ?>
< resources >
<!--Primary colors of the application-->
< color name = "green_200" >#98d5b0</ color >
< color name = "green_light" >#e5f5eb</ color >
< color name = "green_500" >#18ad62</ color >
< color name = "green_700" >#008c4c</ color >
<!--Secondary brand color of the application-->
< color name = "red_200" >#eb8baf</ color >
< color name = "red_700" >#b31058</ color >
<!--Other surface colors and red for error color-->
< color name = "black" >#FF000000</ color >
< color name = "white" >#FFFFFFFF</ color >
< color name = "red" >#B00020</ color >
</ resources >
|
Step 4: Working with the themes.xml files
- Firstly, applying the DayNight DarkActionBar Theme to both light theme and Dark theme of the application as follows:
<style name=”Theme.GFGArticle” parent=”Theme.MaterialComponents.DayNight.DarkActionBar”>
- Following the Color System provided by Material Design Guidelines as discussed above the following are the color system applied for the light theme and dark theme of the application.
- The following values\theme.xml is applied when the application is under the light theme.
<!-- Base application theme. -->
< style name = "Theme.GFGArticle" parent = "Theme.MaterialComponents.DayNight.DarkActionBar" >
<!-- Primary brand color. -->
< item name = "colorPrimary" >@color/green_500</ item >
< item name = "colorPrimaryVariant" >@color/green_700</ item >
< item name = "colorOnPrimary" >@color/white</ item >
<!-- Secondary brand color. -->
< item name = "colorSecondary" >@color/teal_200</ item >
< item name = "colorSecondaryVariant" >@color/teal_700</ item >
< item name = "colorOnSecondary" >@color/black</ item >
<!-- Status bar color. -->
< item name = "android:statusBarColor" tools:targetApi = "l" >?attr/colorPrimaryVariant</ item >
<!-- Customize your theme here. -->
</ style >
</ resources >
|
- The following values-night\themes.xml is applied when the application is under dark theme.
<!-- Base application theme. -->
< style name = "Theme.GFGArticle" parent = "Theme.MaterialComponents.DayNight.DarkActionBar" >
<!-- Primary brand color. -->
< item name = "colorPrimary" >@color/green_200</ item >
< item name = "colorPrimaryVariant" >@color/green_700</ item >
< item name = "colorOnPrimary" >@color/black</ item >
<!-- Secondary brand color. -->
< item name = "colorSecondary" >@color/red_200</ item >
< item name = "colorSecondaryVariant" >@color/red_200</ item >
< item name = "colorOnSecondary" >@color/black</ item >
<!-- Status bar color. -->
< item name = "android:statusBarColor" tools:targetApi = "l" >?attr/colorPrimaryVariant</ item >
<!-- Customize your theme here. -->
</ style >
</ resources >
|
- Have a look at the following images where these files reside inside the Android Studio Project.
Step 5: Working with activity_main.xml file
- The main layout of the application consists of the Material Design Type system. And one Extended Floating Action Button and one Normal Floating Action Button to Demonstrate The secondary brand color of the application.
- All the text views in the layout inherit the style of the Material type system. For example – “style=”@style/TextAppearance.MaterialComponents.Headline4”.
<? xml version = "1.0" encoding = "utf-8" ?>
< androidx.constraintlayout.widget.ConstraintLayout android:layout_width = "match_parent"
android:layout_height = "match_parent"
tools:context = ".MainActivity"
tools:ignore = "HardcodedText" >
<!--Switch button to toggle between the Light and Dark Mode-->
< com.google.android.material.switchmaterial.SwitchMaterial
android:id = "@+id/switchMaterial"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_marginStart = "16dp"
android:layout_marginTop = "16dp"
android:checked = "false"
android:text = "SWITCH TO DARK MODE"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toTopOf = "parent" />
< LinearLayout
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
android:layout_margin = "4dp"
android:clipToPadding = "false"
android:orientation = "vertical"
android:padding = "16dp"
app:layout_constraintBottom_toTopOf = "@+id/extendedFloatingActionButton"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toBottomOf = "@+id/switchMaterial" >
<!--TextView with the Headline 4 as Material type system-->
< TextView
style = "@style/TextAppearance.MaterialComponents.Headline4"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "HEADLINE 4" />
<!--TextView with the Headline 5 as Material type system-->
< TextView
style = "@style/TextAppearance.MaterialComponents.Headline5"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "HEADLINE 5" />
<!--TextView with the Headline 6 as Material type system-->
< TextView
style = "@style/TextAppearance.MaterialComponents.Headline6"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "HEADLINE 6" />
<!--TextView with the Subtitle 1 as Material type system-->
< TextView
style = "@style/TextAppearance.MaterialComponents.Subtitle1"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "SUBTITLE 1" />
<!--TextView with the Subtitle 2 as Material type system-->
< TextView
style = "@style/TextAppearance.MaterialComponents.Subtitle2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "SUBTITLE 2" />
<!--TextView with the Body 1 as Material type system-->
< TextView
style = "@style/TextAppearance.MaterialComponents.Body1"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Body 1" />
<!--TextView with the Body 2 as Material type system-->
< TextView
style = "@style/TextAppearance.MaterialComponents.Body2"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Body 2" />
<!--TextView with the Buttons as Material type system-->
<!--However this type system is applied to text inside the buttons only-->
< TextView
style = "@style/TextAppearance.MaterialComponents.Button"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "TEXT VIEW FOR BUTTON" />
<!--TextView with the Caption as Material type system-->
< TextView
style = "@style/TextAppearance.MaterialComponents.Caption"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "Caption" />
<!--TextView with the Overline texts as Material type system-->
< TextView
style = "@style/TextAppearance.MaterialComponents.Overline"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "OVERLINE" />
<!--Buttons to demonstrate, how Material dark theme changes
the primary color's contrast
when switched from light theme to dark theme-->
< Button
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "BUTTON 1" />
< Button
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:text = "BUTTON 2" />
</ LinearLayout >
<!--Floating action buttons to demonstrate how the
secondary brand color of the application can be used-->
< com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_marginEnd = "16dp"
android:layout_marginBottom = "16dp"
android:src = "@drawable/ic_add"
app:layout_constraintBottom_toBottomOf = "parent"
app:layout_constraintEnd_toEndOf = "parent" />
< com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id = "@+id/extendedFloatingActionButton"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_marginStart = "16dp"
android:layout_marginBottom = "16dp"
android:text = "EXTENDED FAB"
app:icon = "@drawable/ic_add"
app:layout_constraintBottom_toBottomOf = "parent"
app:layout_constraintStart_toStartOf = "parent" />
</ androidx.constraintlayout.widget.ConstraintLayout >
|
Output UI:
Step 6: Working with the MainActivity.kt file
Inside the MainActivity.kt file it’s been handled the checked change listener of the material switch button. And if the device won’t support the dark theme of the application, this project itself supports the dark theme version for all kinds of APIs.
package com.aditya.gfgarticle
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.app.AppCompatDelegate
import com.google.android.material.switchmaterial.SwitchMaterial
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Instance for the material switch
val switchMaterial: SwitchMaterial = findViewById(R.id.switchMaterial)
// handle the checked changes for the material switch
switchMaterial.setOnCheckedChangeListener { buttonView, isChecked ->
when (isChecked) {
// if checked toggle to dark mode
true -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
// if unchecked toggle back to light mode
false -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}
}
}
} |
Output: