By Mohamad Wael

Posted :

Android styles and themes a tutorial

A View has a set of attributes , such as its android:layout_width , or its android:layout_height . Some of these attributes are used to customize the appearance of a view , this is called styling the view , or applying a style to a given view .

This being said , a style can be defined inline , as in the following example :

<?xml version="1.0" encoding="utf-8"?>

<!-- activity_main.xml -->

<LinearLayout ... >

    <Button
        android:background="@android:color/holo_red_light"
        android:textColor="@android:color/white"
        android:focusable="false"
        android:clickable="false"
        ...
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button styled" />

</LinearLayout>
Button styled inline

Or if maybe it is to create a model , like a button model , which will be applied to multiple button views , it can be defined in a resource file , located in the res/values folder .

The res/values folder just contain some files , which contain the definition of some values , such as colors , or strings , or arrays of strings , or dimensions , or styles .

res values folder

Typically styles are defined in a file named style.xml , but the file containing style definitions , can be named anything .

The styling resource file , starts with the resources tag , and contain style tags , where the style tags contain item tags , used to define values for some styling attributes . The next example defines a text appearance style , and a button style :

<!--res/values/styles.xml-->

<resources>

    <style name="eccentric_appearance_text">
        <item name="android:textColor">@android:color/white</item>
        <item name="android:textColorHighlight">@android:color/black</item>
        <item name="android:textColorHint">@android:color/holo_blue_bright</item>
        <item name="android:textSize">22sp</item>
        <item name="android:textStyle">italic</item>
    </style>

    <style name="eccentric_button_style" >
        <item name="android:background">@android:color/holo_red_light</item>
        <item name="android:focusable">false</item>
        <item name="android:clickable">false</item>
        <item name="android:gravity">center_vertical|center_horizontal</item>
        <item name="android:textAppearance">@style/eccentric_appearance_text</item>
    </style>

</resources>

To apply styling to the button , this can be done where the button is defined like so :

<?xml version="1.0" encoding="utf-8"?>

<!-- activity_main.xml -->

<LinearLayout ... >

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/eccentric_button_style"
        android:text="Button styled" />

</LinearLayout>

What will happen , is that the view will parse the attributes specified using xml , and apply the specified styling .

Button styled

A theme has some standard attributes , which it must provide values for , they are defined in the sdk/platforms/android-{version-numer}/data/res/values/attrs.xml file . For example , for android-30 , an excerpt of the attrs.xml file , is the following :

<!-- excerpt from sdk/platforms/android-30/data/res/values/attrs.xml -->

<declare-styleable name="Theme">
    <!-- ============== -->
    <!-- Generic styles -->
    <!-- ============== -->

    <!-- Specifies that a theme has a light background with dark text on top.  -->
    <attr name="isLightTheme" format="boolean" />

    <!-- Default color of background imagery, ex. full-screen windows. -->
    <attr name="colorBackground" format="color" />

    <!-- Color used for error states and things that need to be drawn to
            the users attention.. -->
    <attr name="colorError" format="reference|color" />

    <!-- Default background dim amount when a menu, dialog, or something similar pops up. -->
    <attr name="backgroundDimAmount" format="float" />

    <!-- =========== -->
    <!-- Text styles -->
    <!-- =========== -->

    <!-- Default appearance of text: color, typeface, size, and style. -->
    <attr name="textAppearance" format="reference" />

    <!-- The most prominent text color.  -->
    <attr name="textColorPrimary" format="reference|color" />
    <!-- Secondary text color. -->
    <attr name="textColorSecondary" format="reference|color" />
    <!-- Tertiary text color. -->
    <attr name="textColorTertiary" format="reference|color" />

    <!--  The underline thickness -->
    <attr name="textUnderlineThickness" format="reference|dimension" />

    <!-- ============= -->
    <!-- Button styles -->
    <!-- ============= -->

    <!-- Normal Button style. -->
    <attr name="buttonStyle" format="reference" />

    <!-- Small Button style. -->
    <attr name="buttonStyleSmall" format="reference" />

    <!-- Button style to inset into an EditText. -->
    <attr name="buttonStyleInset" format="reference" />

    <!-- ToggleButton style. -->
    <attr name="buttonStyleToggle" format="reference" />

    <!-- ============== -->
    <!-- Gallery styles -->
    <!-- ============== -->

    <!-- The preferred background for gallery items. This should be set
            as the background of any Views you provide from the Adapter. -->
    <attr name="galleryItemBackground" format="reference" />

    <!-- =========== -->
    <!-- List styles -->
    <!-- =========== -->

    <!-- The preferred list item height. -->
    <attr name="listPreferredItemHeight" format="dimension" />
    <!-- A smaller, sleeker list item height. -->
    <attr name="listPreferredItemHeightSmall" format="dimension" />

    <!-- The preferred TextAppearance for the primary text of list items. -->
    <attr name="textAppearanceListItem" format="reference" />
    <!-- The preferred TextAppearance for the secondary text of list items. -->
    <attr name="textAppearanceListItemSecondary" format="reference" />

    <!-- ============= -->
    <!-- Window styles -->
    <!-- ============= -->

    <attr name="windowBackground" format="reference|color" />
    <attr name="windowBackgroundFallback" format="reference|color" />

    <!-- ============ -->
    <!-- Floating toolbar styles -->
    <!-- ============ -->

    <attr name="floatingToolbarCloseDrawable" format="reference" />
    <attr name="floatingToolbarForegroundColor" format="reference|color" />
    <attr name="floatingToolbarItemBackgroundBorderlessDrawable" format="reference" />

    <!-- ============ -->
    <!-- Alert Dialog styles -->
    <!-- ============ -->

    <attr name="alertDialogStyle" format="reference" />

    <!-- ============== -->
    <!-- Image elements -->
    <!-- ============== -->

    <!-- Icon that should be used to indicate that an app is waiting for a fingerprint scan.
            This should be used whenever an app is requesting the user to place a finger on the
            fingerprint sensor. It can be combined with other drawables such as colored circles, so
            the appearance matches the branding of the app requesting the fingerprint scan.-->
    <attr name="fingerprintAuthDrawable" format="reference" />

    <!-- ============ -->
    <!-- Panel styles -->
    <!-- ============ -->

    <!-- The background of a panel when it is inset from the left and right edges of the screen. -->
    <attr name="panelBackground" format="reference|color" />
    <attr name="panelMenuIsCompact" format="boolean" />
    <attr name="panelMenuListWidth" format="dimension" />
    <attr name="panelMenuListTheme" format="reference" />

    <!-- =================== -->
    <!-- Other widget styles -->
    <!-- =================== -->

    <!-- Default Checkbox style. -->
    <attr name="checkboxStyle" format="reference" />
    <!-- Default EditText style. -->
    <attr name="editTextStyle" format="reference" />
    <!-- Default Gallery style. -->
    <attr name="galleryStyle" format="reference" />
    <!-- Default GridView style. -->
    <attr name="gridViewStyle" format="reference" />
    <!-- Default ListView style. -->
    <attr name="listViewStyle" format="reference" />
    <!-- Default RadioButton style. -->
    <attr name="radioButtonStyle" format="reference" />
    <!-- Default Spinner style. -->
    <attr name="spinnerStyle" format="reference" />
    <!-- NumberPicker style. -->
    <attr name="numberPickerStyle" format="reference" />
    <!-- The CalendarView style. -->
    <attr name="calendarViewStyle" format="reference" />

    <!-- =================== -->
    <!-- Action bar styles   -->
    <!-- =================== -->

    <!-- Default style for tabs within an action bar. -->
    <attr name="actionBarTabStyle" format="reference" />
    <!-- Reference to a style for the Action Bar Tab Bar. -->
    <attr name="actionBarTabBarStyle" format="reference" />
    <!-- Reference to a style for the Action Bar Tab text. -->
    <attr name="actionBarTabTextStyle" format="reference" />

    <!-- =================== -->
    <!-- Action mode styles  -->
    <!-- =================== -->

    <!-- Reference to a style for the Action Mode. -->
    <attr name="actionModeStyle" format="reference" />
    <!-- Reference to a style for the Action Mode close button. -->
    <attr name="actionModeCloseButtonStyle" format="reference" />
    <!-- Background drawable to use for action mode UI. -->
    <attr name="actionModeBackground" format="reference" />

    <!-- =================== -->
    <!-- Preference styles   -->
    <!-- =================== -->

    <!-- Default style for PreferenceScreen. -->
    <attr name="preferenceScreenStyle" format="reference" />
    <!-- Default style for the PreferenceActivity. -->
    <attr name="preferenceActivityStyle" format="reference" />
    <!-- Default style for Headers pane in PreferenceActivity. -->
    <attr name="preferenceFragmentStyle" format="reference" />
    <!-- Default style for PreferenceCategory. -->
    <attr name="preferenceCategoryStyle" format="reference" />
    <!-- Default style for Preference. -->
    <attr name="preferenceStyle" format="reference" />
    <!-- Default style for informational Preference. -->
    <attr name="preferenceInformationStyle" format="reference" />
    <!-- Default style for CheckBoxPreference. -->
    <attr name="checkBoxPreferenceStyle" format="reference" />

    <!-- ============================ -->
    <!-- Text selection handle styles -->
    <!-- ============================ -->

    <!-- Reference to a drawable that will be used to display a text selection
            anchor on the left side of a selection region. -->
    <attr name="textSelectHandleLeft" format="reference" />
    <!-- Reference to a drawable that will be used to display a text selection
            anchor on the right side of a selection region. -->
    <attr name="textSelectHandleRight" format="reference" />


    <!-- Theme to use for dialogs spawned from this theme. -->
    <attr name="dialogTheme" format="reference" />
    <!-- Window decor layout to use in dialog mode with icons. -->
    <attr name="dialogTitleIconsDecorLayout" format="reference" />

    <!-- Theme to use for alert dialogs spawned from this theme. -->
    <attr name="alertDialogTheme" format="reference" />
    <!-- Icon drawable to use for alerts. -->
    <attr name="alertDialogIcon" format="reference" />

    <!-- Style for button bars. -->
    <attr name="buttonBarStyle" format="reference" />

    <!-- Style for buttons within button bars. -->
    <attr name="buttonBarButtonStyle" format="reference" />

    <!-- Background to use for toasts. -->
    <attr name="toastFrameBackground" format="reference" />

    <!-- Background to use for tooltip popups. -->
    <attr name="tooltipFrameBackground" format="reference" />

    <!-- Foreground color to use for tooltip popups. -->
    <attr name="tooltipForegroundColor" format="reference|color" />

    <!-- ============== -->
    <!-- Pointer styles -->
    <!-- ============== -->

    <!-- The drawable for accessibility focused views. -->
    <attr name="accessibilityFocusedDrawable" format="reference" />

    <!-- ============= -->
    <!-- Color palette -->
    <!-- ============= -->

    <!-- The primary branding color for the app. By default, this is the color applied to the
            action bar background. -->
    <attr name="colorPrimary" format="color" />

    <!-- Dark variant of the primary branding color. By default, this is the color applied to
            the status bar (via statusBarColor) and navigation bar (via navigationBarColor). -->
    <attr name="colorPrimaryDark" format="color" />

    <!-- The secondary branding color for the app. -->
    <attr name="colorSecondary" format="color" />

    <!-- Bright complement to the primary branding color. By default, this is the color applied
            to framework controls (via colorControlActivated). -->
    <attr name="colorAccent" format="color" />

    <!-- The color applied to framework controls in their normal state. -->
    <attr name="colorControlNormal" format="color" />

    <!-- The color applied to framework controls in their activated (ex. checked) state. -->
    <attr name="colorControlActivated" format="color" />

    <!-- The color applied to framework control highlights (ex. ripples, list selectors). -->
    <attr name="colorControlHighlight" format="color" />

    <!-- The color applied to framework buttons in their normal state. -->
    <attr name="colorButtonNormal" format="color" />

    <!-- The color applied to framework switch thumbs in their normal state. -->
    <attr name="colorSwitchThumbNormal" format="color" />

    <!-- The color applied to framework progress and seek bar backgrounds in their normal state. -->
    <attr name="colorProgressBackgroundNormal" format="color" />

    <!-- The color applied to the edge effect on scrolling containers. -->
    <attr name="colorEdgeEffect" format="color" />

    <!-- =================== -->
    <!-- Lighting properties -->
    <!-- =================== -->

    <!-- @hide The default Y position of the light used to project view shadows. -->
    <attr name="lightY" format="dimension" />

    <!-- @hide The default Z position of the light used to project view shadows. -->
    <attr name="lightZ" format="dimension" />

    <!-- Alpha value of the ambient shadow projected by elevated views, between 0 and 1. -->
    <attr name="ambientShadowAlpha" format="float" />

    <!-- Alpha value of the spot shadow projected by elevated views, between 0 and 1. -->
    <attr name="spotShadowAlpha" format="float" />

</declare-styleable>

As it can be seen from the attrs.xml file , some attributes are set to have a value , which has a reference format , meaning it must refer to another resource , other attributes are set to must have a literal value , such as a boolean , or a dimension .

An example of a theme , is the holo theme ,which was the default system theme , for application targeting android api , from version 11 inclusive , till version 13 inclusive , and from which an exert is provided :

<!-- excerpt from sdk/platforms/android-30/data/res/values/themes_holo.xml -->

<?xml version="1.0" encoding="utf-8"?>

<resources>
    <style name="Theme.Holo">
        <item name="colorBackground">@color/background_holo_dark</item>
        <item name="colorError">@color/error_color_material_dark</item>
        <item name="backgroundDimAmount">0.6</item>

        <!-- Text styles -->
        <item name="textAppearance">@style/TextAppearance.Holo</item>
        <item name="textAppearanceInverse">@style/TextAppearance.Holo.Inverse</item>

        <item name="textColorPrimary">@color/primary_text_holo_dark</item>
        <item name="textColorSecondary">@color/secondary_text_holo_dark</item>
        <item name="textColorTertiary">@color/tertiary_text_holo_dark</item>

        <!-- Button styles -->
        <item name="buttonStyle">@style/Widget.Holo.Button</item>

        <item name="buttonStyleSmall">@style/Widget.Holo.Button.Small</item>
        <item name="buttonStyleInset">@style/Widget.Holo.Button.Inset</item>

        <item name="buttonStyleToggle">@style/Widget.Holo.Button.Toggle</item>

        <!-- Gallery attributes -->
        <item name="galleryItemBackground">@drawable/gallery_item_background</item>

        <!-- List attributes -->
        <item name="listPreferredItemHeight">64dip</item>
        <item name="listPreferredItemHeightSmall">48dip</item>
        <item name="textAppearanceListItem">?attr/textAppearanceLarge</item>
        <item name="textAppearanceListItemSecondary">?attr/textAppearanceSmall</item>

        <!-- Window attributes -->
        <item name="windowNoTitle">false</item>
        <item name="windowTitleSize">25dip</item>

        <!-- Dialog attributes -->
        <item name="dialogTheme">@style/Theme.Holo.Dialog</item>
        <item name="dialogCornerRadius">0dp</item>

        <!-- AlertDialog attributes -->
        <item name="alertDialogStyle">@style/AlertDialog.Holo</item>

        <!-- Presentation attributes -->
        <item name="presentationTheme">@style/Theme.Holo.Dialog.Presentation</item>

        <!-- Toast attributes -->
        <item name="toastFrameBackground">@drawable/toast_frame</item>

        <!-- Panel attributes -->
        <item name="panelBackground">@drawable/menu_hardkey_panel_holo_dark</item>
        <item name="panelMenuIsCompact">true</item>
        <item name="panelMenuListWidth">250dip</item>
        <item name="panelMenuListTheme">@style/Theme.Holo.CompactMenu</item>

        <!-- Widget styles -->
        <item name="checkboxStyle">@style/Widget.Holo.CompoundButton.CheckBox</item>
        <item name="editTextStyle">@style/Widget.Holo.EditText</item>
        <item name="galleryStyle">@style/Widget.Holo.Gallery</item>
        <item name="gridViewStyle">@style/Widget.Holo.GridView</item>
        <item name="listViewStyle">@style/Widget.Holo.ListView</item>
        <item name="listViewWhiteStyle">@style/Widget.Holo.ListView.White</item>
        <item name="radioButtonStyle">@style/Widget.Holo.CompoundButton.RadioButton</item>
        <item name="spinnerStyle">?attr/dropDownSpinnerStyle</item>

        <!-- Action bar styles -->
        <item name="actionBarTabStyle">@style/Widget.Holo.ActionBar.TabView</item>
        <item name="actionBarTabBarStyle">@style/Widget.Holo.ActionBar.TabBar</item>
        <item name="actionBarTabTextStyle">@style/Widget.Holo.ActionBar.TabText</item>

        <!-- Preference styles -->
        <item name="preferenceScreenStyle">@style/Preference.Holo.PreferenceScreen</item>
        <item name="preferenceActivityStyle">@style/PreferenceActivity</item>
        <item name="preferenceFragmentStyle">@style/PreferenceFragment.Holo</item>
        <item name="preferenceCategoryStyle">@style/Preference.Holo.Category</item>
        <item name="preferenceStyle">@style/Preference.Holo</item>
        <item name="preferenceInformationStyle">@style/Preference.Holo.Information</item>
        <item name="checkBoxPreferenceStyle">@style/Preference.Holo.CheckBoxPreference</item>

        <!-- Text selection handle attributes -->
        <item name="textSelectHandleLeft">@drawable/text_select_handle_left_material</item>
        <item name="textSelectHandleRight">@drawable/text_select_handle_right_material</item>

        <!-- Scrollbar attributes -->
        <item name="scrollbarFadeDuration">250</item>
        <item name="scrollbarSize">10dip</item>
        <item name="scrollbarThumbHorizontal">@drawable/scrollbar_handle_holo_dark</item>
        <item name="scrollbarThumbVertical">@drawable/scrollbar_handle_holo_dark</item>

        <!-- Search widget styles -->
        <item name="searchWidgetCorpusItemBackground">@color/search_widget_corpus_item_background</item>

        <!-- SearchView attributes -->
        <item name="searchViewStyle">@style/Widget.Holo.SearchView</item>
        <item name="searchDialogTheme">@style/Theme.Holo.SearchBar</item>

        <!-- PreferenceFrameLayout attributes -->
        <item name="preferenceFrameLayoutStyle">@style/Widget.Holo.PreferenceFrameLayout</item>

        <!-- NumberPicker style-->
        <item name="numberPickerStyle">@style/Widget.Holo.NumberPicker</item>

        <!-- CalendarView style-->
        <item name="calendarViewStyle">@style/Widget.Holo.CalendarView</item>

        <!-- TimePicker style -->
        <item name="timePickerStyle">@style/Widget.Holo.TimePicker</item>

        <!-- TimePicker dialog theme -->
        <item name="timePickerDialogTheme">?attr/alertDialogTheme</item>

        <!-- DatePicker style -->
        <item name="datePickerStyle">@style/Widget.Holo.DatePicker</item>

        <!-- DatePicker dialog theme -->
        <item name="datePickerDialogTheme">?attr/alertDialogTheme</item>

        <item name="colorPrimaryDark">@color/holo_primary_dark</item>
        <item name="colorPrimary">@color/holo_primary</item>
        <item name="colorAccent">@color/holo_blue_dark</item>
        <item name="colorEdgeEffect">?attr/colorPrimary</item>

        <item name="colorControlNormal">@color/holo_control_normal</item>
        <item name="colorControlActivated">@color/holo_control_activated</item>

        <item name="colorControlHighlight">@color/holo_button_pressed</item>
        <item name="colorButtonNormal">@color/holo_button_normal</item>
        <item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>

        <!-- Holo-only color attributes -->
        <item name="colorPressedHighlight">@color/holo_gray_light</item>
        <item name="colorLongPressedHighlight">@color/holo_gray_bright</item>
        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>

    </style>
</resources>

So as it can be seen from the provided excerpt , a theme is also defined using the style tag , in a ressource file inside the res/values folder . For the holo theme , this file is named themes_holo.xml .

In a sense , the attributes which a theme defines , have a higher degree of abstraction . So for example , for button styling , the buttonStyleSmall attribute was specified in the attrs.xml file , as to be defined , and is defined in themes_holo.xml , as having the value of @style/Widget.Holo.Button.Small . @style/Widget.Holo.Button.Small is defined in sdk/platforms/android-30/data/res/values/res/values/styles_holo.xml as :

<style name="Widget.Holo.Button.Small">
    <item name="background">@drawable/btn_default_holo_dark</item>
    <item name="textAppearance">?attr/textAppearanceSmall</item>
    <item name="textColor">@color/primary_text_holo_dark</item>
    <item name="minHeight">48dip</item>
    <item name="minWidth">48dip</item>
</style>

So in other words , different themes can define different values for the buttonStyleSmall attribute , and as an application developper , if you want to model by using themes , you can specify a style attribute for a View , for example the button , by using style="?android:attr/buttonStyleSmall" , where ?android:attr/buttonStyleSmall means , get the value of the android defined attribute , buttonStyleSmall , which is set , in the current set theme .

So whatever theme you set for your application , given the fact that you can also change a theme programmatically , or you can not specify a theme , to default to the device default theme , what is being stated is that in all cases , the button must have a styling of button small , so in other words , switching a theme , can switch the style while keeping the intended meaning , and going with the designer conceptions .

Also note that for example , the buttonStyle , which is defined in a theme , as <item name="buttonStyle">@style/Widget.Holo.Button</item> , will be applied by default to all buttons , to which the theme is set for , for example in the activity , or in a viewgroup .

A fallback theme , can be specified for all the activities in an application , by using the AndroidManifest.xml file . A theme can be specified for an activity , for a ViewGroup such as LinearLayout , for a specific View such as a Button .

<?xml version="1.0" encoding="utf-8"?>
<!-- AndroidManifest.xml -->

<manifest ...>

    <application ...
        android:theme="@style/AppTheme">

        <activity
            android:name=".MainActivity"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar" >
            ...
        </activity>
    </application>

</manifest>

<?xml version="1.0" encoding="utf-8"?>
<!-- activity_main.xml -->

<LinearLayout ...
    android:theme="@android:style/Theme.DeviceDefault" >

    <Button
        ...
        style="?android:attr/buttonStyleSmall" />

    <Button
        ...
        style="@android:style/Widget.Holo.Button.Small" />    

</LinearLayout>

Applying the theme at a higher level , will make it be inherited at a lower level . So a theme applied to an activity , makes it appliable to its root ViewGroup , if its root ViewGroup , does not specify a theme . The views children of the ViewGroup will also inherit its theme , if they do not specify their own .

In other words , if no theme is specified , higher levels are checked for a theme , if an activity does not specify a theme , the application fallback theme is used , if the application does not specify a theme , then the default theme is used .

The default theme is selected based on the default target sdk version :

If the target sdk is lower than 11 , which is HONEYCOMB , then the default theme is com.android.internal.R.style.Theme , which is @android:style/Theme .

If the target sdk is larger or equal to 11 , and less than 14 , which is ICE_CREAM_SANDWICH , then the default theme will be com.android.internal.R.style.Theme_Holo , which is @android:style/Theme.Holo .

If the target sdk is larger or equal to 14 , and less than 24 , which is android Nougat , then the default theme will be com.android.internal.R.style.Theme_DeviceDefault , which is @android/style/Theme.DeviceDefault . For android platform 30 , this theme has a parent of Theme.DeviceDefaultBase , which has a parent of Theme.Material . Theme.DeviceDefault can be customized by device manufacturor , for example , on older google nexus devices , Theme.DeviceDefault was actually an alias to the Holo theme .

If the target sdk is larger or equal to android version 24 , the default theme is com.android.internal.R.style.Theme_DeviceDefault_Light_DarkActionBar , which is @android:style/Theme.DeviceDefault.Light.DarkActionBar .

If multiple themes are assigned down the hierarchy , for example if one theme is assigned for the activity , a second one is assigned to the activity root ViewGroup , and a third one , on a View in that ViewGroup , then the most local one applies . Attributes which are defined in a higher level of the hierarchy , but which do not exist in the lower level , are also applied .

So in other words , it is like composing themes together , and this brings us to what is called overlay themes , which might be encountered as in android:theme="@android:style/ThemeOverlay.Material.Light" . Overlay themes , define a limited set of attributes , as to be composed with other themes .

<!-- sdk/platforms/android-30/data/res/values -->

<!-- Theme overlay that replaces colors with their light versions but preserves
        the value of colorAccent, colorPrimary and its variants. -->

<style name="ThemeOverlay.Material.Light">
    <item name="colorForeground">@color/foreground_material_light</item>
    <item name="colorForegroundInverse">@color/foreground_material_dark</item>
    <item name="colorBackground">@color/background_material_light</item>
    <item name="colorBackgroundFloating">@color/background_floating_material_light</item>
    <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_light</item>
    <item name="colorError">@color/error_color_material_light</item>

    <item name="textColorPrimary">@color/text_color_primary</item>
    <item name="textColorPrimaryInverse">@color/primary_text_material_dark</item>
    <item name="textColorSecondary">@color/text_color_secondary</item>
    <item name="textColorSecondaryInverse">@color/secondary_text_material_dark</item>
    <item name="textColorTertiary">@color/secondary_text_material_light</item>
    <item name="textColorTertiaryInverse">@color/secondary_text_material_dark</item>
    <item name="textColorPrimaryDisableOnly">@color/primary_text_disable_only_material_light</item>
    <item name="textColorPrimaryInverseDisableOnly">@color/primary_text_disable_only_material_dark</item>
    <item name="textColorHint">@color/hint_foreground_material_light</item>
    <item name="textColorHintInverse">@color/hint_foreground_material_dark</item>
    <item name="textColorHighlight">@color/highlighted_text_material</item>
    <item name="textColorHighlightInverse">@color/highlighted_text_material</item>
    <item name="textColorSearchUrl">@color/search_url_text_material_light</item>
    <item name="textColorAlertDialogListItem">@color/primary_text_material_light</item>

    <item name="textCheckMark">@drawable/indicator_check_mark_light</item>
    <item name="textCheckMarkInverse">@drawable/indicator_check_mark_dark</item>

    <item name="colorControlNormal">?attr/textColorSecondary</item>
    <item name="colorControlHighlight">@color/ripple_material_light</item>
    <item name="colorButtonNormal">@color/btn_default_material_light</item>
    <item name="colorSwitchThumbNormal">@color/switch_thumb_material_light</item>
    <item name="colorProgressBackgroundNormal">?attr/colorControlNormal</item>
</style>

The AppCompat support library , which provides backwards compatibility for older android versions , has some themes which are defined , and which start by Theme.AppCompat , or by ThemeOverlay.AppCompat , and which can be used as in android:theme="@style/Theme.AppCompat" or as in style="?attr/buttonStyleSmall" so without prefixing with android: , as in to dereference an attribute which belongs or has been defined by the application . If an activity extends an AppCompatActivity , it must use an AppCompat theme .

Generally in the android platform , or in AppCompat , the themes are either dark themes which use a dark bacground color , with a light foreground such as one used for text , or light themes , and they do , or do not have , an action bar . Light themes can also have a dark action bar .

There is also what is called a DayNight theme , like Theme.AppCompat.DayNight or Theme.DeviceDefault.DayNight . A DayNight theme switches between a dark and a light theme , as instructed to do by using the setDefaultNightMode method , of AppCompatDelegate , as follows .

<!-- app/src/main/AndroidManifest.xml -->

<?xml version="1.0" encoding="utf-8"?>

<manifest ...>

    <application
        android:name=".TheApp"
        android:theme="@style/Theme.AppCompat.DayNight">
        <activity ...
    </application>

</manifest>
/* src/main/java/com/twiserandom/mobileapps/demo/theme_and_style/TheApp.java */

package com .twiserandom .mobileapps .demo .theme_and_style;

import android .app .Application;
import androidx .appcompat .app .AppCompatDelegate;

public class
        TheApp
            extends Application {

    public void
            onCreate ( ){
        super .onCreate ( );
        AppCompatDelegate .setDefaultNightMode (AppCompatDelegate .MODE_NIGHT_AUTO );
    /*
        MODE_NIGHT_AUTO_BATTERY : 
            When battery saver is on , use the dark theme , 
            otherwise use the light theme . 
        MODE_NIGHT_YES : 
            use the dark theme .
        MODE_NIGHT_NO : 
            use the light theme .
        MODE_NIGHT_AUTO , MODE_NIGHT_AUTO_TIME : 
            use the dark theme , when determined by using
            the location or if not possible hardcoded time ,
            that it is night . This is deprecated .
        MODE_NIGHT_FOLLOW_SYSTEM : 
            use the system night mode setting ,
            to determine if the dark theme is to be used . */ }}

A DayNight theme works by having values for the night category , defined in values-night , so for example Theme.AppCompat.DayNight has values defined in both appcompat-version/res/values/values.xml as <style name="Theme.AppCompat.DayNight" parent="Theme.AppCompat.Light"/> , and appcompat-version/res/values-night-v8/values-night-v8.xml as <style name="Theme.AppCompat.DayNight" parent="Theme.AppCompat"/> , values-night-v8 means this applies starting api version 8 only .

Starting android version 10 , nicknamed Q , which is api version 29 , it is possible to set the phone theme to a dark theme , by using system settings , hence applications that uses the day and night themes , will automatically switch to the dark theme , unless they have this overriden , as shown earlier .

When an android application is created , it has a default fallback theme , declared in the AndroidManifest.xml .

<?xml version="1.0" encoding="utf-8"?>

<!-- app/src/main/AndroidManifest.xml -->

<manifest ... >

    <application ...
        android:theme="@style/AppTheme">
        ...
    </application>

</manifest>

AppTheme is defined in the application res/values/styles.xml , and has the following content :

<!-- app/src/main/res/values/styles.xml -->

<resources>

    <!-- Base application theme. -->

    <style
            name="AppTheme"
            parent="Theme.AppCompat.Light.DarkActionBar">

        <!-- Customize your theme here. -->

        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

So when defining a theme , or a style , a parent can be specified , as seen from the previous example , as not to start from scratch . For a style , it can be done like so :

<!-- app/src/main/res/values/styles.xml -->    
<resources>
    <style 
            name="eccentric_appearance_text" 
            parent="@android:style/TextAppearance.Inverse">
            <!-- 
                To inherit from within the android platform
                sdk/platforms/android-version/data/res/values/styles.xml ,
                the @android:style/What_To_inherit format can 
                be used .
                For example AppTheme can inherit the 
                Theme.DeviceDefault.Light by using 
                parent="@android:style/Theme.DeviceDefault.Light"
            -->
        <item name="android:textColor">@android:color/white</item>
        <item name="android:textSize">22sp</item>
        <item name="android:textStyle">italic</item>
    </style>

    <style 
            name="eccentric_appearance_text.eccentric_button_style"  
            parent="@style/eccentric_appearance_text" >
        <!-- 
            To inherit from within the
                application  , or within a library in the
                application such as AppCompat , the @android:
                prefix can be dropped  , you can even drop
                the @style/ if you want .
            So for example eccentric_button_style , can define
                a parent of parent="TextAppearance.AppCompat" ,
                to specify that its parent style belong to 
                the AppCompat library .
            Also inheritance within the application , not within
                libraries that application is using , can be done
                using a dot notation in the name , of the like ,
                name="eccentric_appearance_text.eccentric_button_style" ,
                to specify that eccentric_button_style has a
                parent of eccentric_appearance_text .
                In such a case it is not necessary to use the
                parent attribute , but if the parent attribute
                is used , then the styling inherited using
                the parent attribute has higher precedence
                over styling inherited using the dot notation .
                When  specifying the style  , the complete
                dotted name must be used as in
                style="@style/eccentric_appearance_text.eccentric_button_style" -->
        <item name="android:background">@android:color/holo_red_light</item>
        <item name="android:textColor">@android:color/white</item>
        <item name="android:focusable">false</item>
        <item name="android:clickable">false</item>
        <item name="android:gravity">center_vertical|center_horizontal</item>
    </style>

</resources>

When applying android:theme , and style to a view , the style attributes will have a higher priority than the theme attributes , and inline attributes will have a higher priority than both the theme , and the style attributes , and styling attributes which are set programmatically , will have the higher priority .

<?xml version="1.0" encoding="utf-8"?>

<!-- res/layout/activity_main.xml -->

<LinearLayout ... >

    <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/btn"
            style="@style/eccentric_appearance_text.eccentric_button_style"
            android:theme="@android:style/Theme.Holo"
            android:textColor="@android:color/holo_green_dark"
            android:text="Button styled" />
        <!--
            Attributes defined in 
            style="@style/eccentric_appearance_text.eccentric_button_style"
            have a higher priority than attributes 
            defined in android:theme="@android:style/Theme.Holo"  ,
            but they have a lesser priority than  inline 
            defined attributes  of the like of :
            android:textColor="@android:color/holo_green_dark" , 
            which have a lower priority of styling attributes 
            set programmatically , as  in ,
            Button btn = (Button) findViewById(R.id.btn);
            btn.setTextColor(Color.BLUE); -->
</LinearLayout>

In newer version of androd studio , the default fallback theme , declared in AndroidManifest.xml , and which is used to customize an application theming , had a name change , and is now :

<?xml version="1.0" encoding="utf-8"?>
<!-- AndroidManifest.xml -->
<manifest ... >
    <application
        android:theme="@style/Theme.ThemeAndStyle">
        <!-- 
                The application name is actually 
                Theme And Style , so ThemeAndStyle
                is the application name with spaces 
                being removed . -->
        <activity  ...
    </application>
</manifest>

Theme.[ApplicationName] is defined in res/values/themes.xml and res/values-night/themes.xml . So one is the light theme , and the second one is the dark theme .

<!-- res/values/themes.xml -->
<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.ThemeAndStyle" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_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>

<!-- res/values-night/themes.xml -->
<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.ThemeAndStyle" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_200</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/black</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_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>

As seen from the previous excerpt , Theme.[ApplicationName] has a parent of Theme.MaterialComponents.DayNight.DarkActionBar which is a new theme by google , defined in a new library called material components , and which can be gotten by adding to the build.gradle dependencies , the following content :

dependencies {
    ...
    implementation 'com.google.android.material:material:<version>'
    // for example , implementation 'com.google.android.material:material:1.1.0'
    ...
}

The material components library defines , a dark theme Theme.MaterialComponents , and a light theme Theme.MaterialComponents.Light , and a day and night theme Theme.MaterialComponents.DayNight , which all can or cannot have an action bar , as in Theme.MaterialComponents.DayNight.NoActionBar . Additionally , the day and night theme , and the light theme , can have a dark action bar , as in Theme.MaterialComponents.Light.DarkActionBar .

The material components library , also defines what is called a bridge theme , this is like , if you were using in an older application , an AppCompat theme, and you want to switch the theme to the new material component theme , but some constraints forbid you of doing so , then you can use a bridge theme as in Theme.MaterialComponents.Bridge . Bridge themes inherit from AppCompat themes , and newer theming must be explicitly enabled , as not to cause attributes errors . For bridge themes , there is a dark and a light version , both with or without an action bar . The light version can also have a dark action bar .

<!-- res/values/themes.xml -->
<resources ...>
    <style 
            name="Theme.ThemeAndStyle" 
            parent="Theme.MaterialComponents.Bridge">
        <item 
            name="materialButtonStyle">
                @style/Widget.MaterialComponents.Button
        </item>
        <!-- explicitly enabling newer theming  .-->
    </style>
</resources>

A theme as seen earlier , has a color palette , each application can customize it , as its branding sees fit . To understand how color applies to a theme , google has provided a color tool .

Google color tool material palette

In comparison with the older theming color attributes specified in AppCompat , or the android api framework used version , the material component library colorPrimary maps to colorPrimary , and colorPrimaryVariant maps to colorPrimaryDark , and colorSecondary maps to colorAccent , and the material component library defines additional coloring attributes .

To customize a theme , it can be done by using xml . In android studio 3.2 , and earlier versions , there was the theme editor tool , but it was removed , starting android 3.3 .

So customizing a theme , is like defining your designer vision , so it is just about defining the values for some models , or attributes , or just creating some totally new attributes . So if the colors are downloaded from the material color tool , and placed in res/values/colors.xml they will have the following definition :

<?xml version="1.0" encoding="utf-8"?>

<!-- res/values/colors.xml -->

<resources>
    ...
    <color name="primaryColor">#64b5f6</color>
    <color name="primaryLightColor">#9be7ff</color>
    <color name="primaryDarkColor">#2286c3</color>
    <color name="secondaryColor">#b71c1c</color>
    <color name="secondaryLightColor">#f05545</color>
    <color name="secondaryDarkColor">#7f0000</color>
    <color name="primaryTextColor">#000000</color>
    <color name="secondaryTextColor">#ffffff</color>
    </resources>

And to apply them in the day theme , and to customize it , a little bit further more , this can be done like so :

<!-- /res/values/themes.xml -->
<resources xmlns:tools="http://schemas.android.com/tools">

    <!-- define some custom attributes -->
    <attr name="MyHeadline6" format="reference"/>
    <attr name="MyHeadline7" format="reference"/>
    
    <!-- Define some styles   -->    
    <style
            name="MyHeadline6"
            parent="TextAppearance.MaterialComponents.Headline6">
        <item name="textAllCaps">true</item>
    </style>

    <style
            name="MyHeadline7" >
        <item name="fontFamily">sans-serif-thin</item>
        <item name="android:fontFamily">sans-serif-thin</item>
        <item name="android:textStyle">normal</item>
        <item name="android:textAllCaps">false</item>
        <item name="android:textSize">14sp</item>
        <item name="android:letterSpacing">0.009375</item>
    </style>

    <style
            name="shapeAppearanceSmallComponent"
            parent="ShapeAppearance.MaterialComponents.SmallComponent">
        <item name="cornerFamily">cut</item>
        <item name="cornerSize">24dp</item>
    </style>

    <style
            name="materialButtonStyle"
            parent="Widget.MaterialComponents.Button">
        <item name="android:textColor">@android:color/holo_orange_dark</item>
    </style>
    
    <!-- Define a custom theme  -->
    <style
            name="Theme.ThemeAndStyle"
            parent="Theme.MaterialComponents.DayNight.DarkActionBar">

        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/primaryColor</item>
        <item name="colorPrimaryVariant">@color/primaryDarkColor</item>
        <item name="colorOnPrimary">@color/primaryTextColor</item>

        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/secondaryColor</item>
        <item name="colorSecondaryVariant">@color/secondaryDarkColor</item>
        <item name="colorOnSecondary">@color/secondaryTextColor</item>

        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>

        <!-- custom modeling -->
        <item name="MyHeadline7">@style/MyHeadline7</item>
        <item name="MyHeadline6">@style/MyHeadline6</item>

        <!-- Overriding material button modeling  -->
        <item name="materialButtonStyle">@style/materialButtonStyle</item>
    </style>
</resources>

And if the res/layout/activity_main.xml has the following content :

<?xml version="1.0" encoding="utf-8"?>

<!-- res/layout/activity_main.xml -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <com.google.android.material.button.MaterialButton
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?attr/textAppearanceHeadline6"
        app:shapeAppearance="?attr/shapeAppearanceSmallComponent"
        android:text="hello world"  />

    <com.google.android.material.button.MaterialButton
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?MyHeadline6"
        app:shapeAppearance="@style/shapeAppearanceSmallComponent"
        android:text="hello world"  />

    <com.google.android.material.button.MaterialButton
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?MyHeadline7"
        android:text="hello world"  />

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <CalendarView
        android:id="@+id/calendarView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <SeekBar
        android:id="@+id/seekBar2"
        style="@style/Widget.AppCompat.SeekBar.Discrete"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="10"
        android:progress="3" />

    <Switch
        android:id="@+id/switch1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Switch" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floatingActionButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        app:srcCompat="@android:drawable/ic_input_add" />


</LinearLayout>

Then the outcome will be the following :

Theme and style app

Finally as stated earlier , a theme can be set programmatically , using the settheme method , as in the following code fragment .

import androidx .appcompat .app .AppCompatActivity;
import android .os .Bundle;

public class 
        MainActivity 
            extends AppCompatActivity {

    @Override
    protected void 
            onCreate 
                (Bundle savedInstanceState ){
        super .onCreate (savedInstanceState );
        setTheme (R .style .Theme_MaterialComponents_NoActionBar_Bridge );
        /* setTheme must be called before 
           any views are instantiated in 
           the Context , so for example 
           before setContentView is 
           called .*/
        setContentView (R .layout .activity_main ); } }