Android Material Themes Demo

repository·master·Indexed 19 days ago

https://github.com/stevenbyle/android-material-themes-demo

A demo application and educational guide for creating dynamically colorized Material Design applications. It demonstrates the use of themes, styles, and the v7 AppCompat Support Library to implement branding and dynamic coloring across Android devices, including legacy versions back to API 7. The guide covers defining global attributes, configuring AppCompat themes, and styling components such as Buttons, FloatingActionButtons, TextInputLayout, and custom selectable items.

Tokens
4.1K
Snippets
10
Records
14
Agent score
17%

What's inside android-material-themes-demo

  1. Requirements for using AppCompat for Material UI

    master

    To use Material UI elements with dynamic color tinting on devices running Android 2.1+, you must satisfy three requirements for the AppCompat Support Library to function correctly:

    1. Activity Type: Every Activity used must extend AppCompatActivity or implement AppCompatDelegate.
    2. Theme/Style Inheritance: All applied themes and styles must extend from AppCompat versions.
    3. Attribute Configuration: You must set the custom theme attributes specifically designed for AppCompat themes and styles.

    When these conditions are met, AppCompatActivity intercepts layouts during inflation and wraps supported Views with their AppCompat counterparts. These views then read the custom AppCompat theme attributes to dynamically colorize themselves, ensuring backwards compatibility.

  2. How Styles and Themes work in Android

    master

    Android uses two distinct but related concepts for customization:

    • Styles: A collection of attributes applied to individual Views (e.g., a specific TextView). Styles allow you to group properties like colors, dimensions, and fonts so they can be reused across many components. They support inheritance to create variations.
    • Themes: A collection of global attributes applied at the Activity or Application level. Themes define the overall look and feel (default colors, sizes, etc.) for the entire app or screen.

    The Relationship: Themes provide a palette of global attributes (e.g., android:textColorPrimary). Styles then reference these theme attributes (using the ? syntax) to apply them to specific Views. This decoupling allows you to change the entire app's branding by updating the theme without modifying individual styles or layout files.

  3. Define a complete AppCompat theme set

    master

    To implement a consistent Material theme using AppCompat, you should define three distinct styles: an application theme, a dialog theme, and an alert dialog theme. The application theme sets the primary color palette (using colorPrimary, colorPrimaryDark, and colorAccent) and points to the specific dialog themes via the dialogTheme and alertDialogTheme attributes. This ensures that all components, including popups, inherit the correct color scheme.

    <!-- Green App Theme -->
    <style name="AppTheme.Green" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        
        <!-- AppCompat Attributes -->
        <item name="colorPrimary">@color/material_green_500</item>
        <item name="colorPrimaryDark">@color/material_green_700</item>
        <item name="colorAccent">@color/material_green_a700</item>
    
        <!-- AppCompat Dialog Attributes -->
        <item name="dialogTheme">@style/AppTheme.Dialog.Green</item>
        <item name="alertDialogTheme">@style/AppTheme.Dialog.Alert.Green</item>
    </style>
    
    <!-- Green Dialog Theme -->
    <style name="AppTheme.Dialog.Green" parent="Theme.AppCompat.Light.Dialog">
        <item name="colorPrimary">@color/material_green_500</item>
        <item name="colorPrimaryDark">@color/material_green_700</item>
        <item name="colorAccent">@color/material_green_a700</item>
    </style>
    
    <!-- Green Alert Dialog Theme -->
    <style name="AppTheme.Dialog.Alert.Green" parent="Theme.AppCompat.Light.Dialog.Alert">
        <item name="colorPrimary">@color/material_green_500</item>
        <item name="colorPrimaryDark">@color/material_green_700</item>
        <item name="colorAccent">@color/material_green_a700</item>
    </style>
  4. Apply a theme to an individual View or ViewGroup

    master

    While themes are typically set at the Application or Activity level, you can override the theme for a specific View or ViewGroup using the android:theme attribute. AppCompatActivity will correctly intercept and apply these theme attributes during layout inflation.

    <View
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:theme="@style/AppTheme.Green"/>
  5. Implement dynamic coloring with AppCompat

    master

    To support Material Design features like color tinting and theme-aware ShapeDrawables on legacy devices (below Android 5.0/API 21), use the v7 AppCompat Support Library.

    AppCompat provides "tint-aware" material design UI elements that allow for dynamic colorization and theme attribute access on devices as old as Android 2.1 (API 7). This avoids the need to generate multiple raster assets (PNGs) for every color/state combination.

  6. Use attributes to create dynamic themes

    master

    Attributes act like variables for UI properties. To create a flexible, dynamic theme, you should avoid hardcoding values in styles. Instead, define global colors in a theme and reference them in your styles using the ? prefix.

    1. Define the global attribute in a theme: Set a theme-level attribute like android:textColorPrimary to a specific color.
    2. Reference the attribute in a style: In your component style, set a view-specific attribute (like android:textColor) to the theme attribute (?android:textColorPrimary).

    This allows the UI to update automatically when the theme changes at runtime.

    <!-- 1. Define global color in the theme -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    	<item name="android:textColorPrimary">#00FF00</item>
    </style>
    
    <!-- 2. Reference that global color in a component style -->
    <style name="TextStyle" parent="TextAppearance.AppCompat">
    	<item name="android:textColor">?android:textColorPrimary</item>
    </style>
  7. Create custom selectable items with SelectableItemStyle

    master

    You can create custom elements that use theme attributes to show pressed states on arbitrary layouts (like ViewGroup) by applying specific styles. This allows for backwards-compatible, theme-aware selection effects.

    Available styles:

    • @style/SelectableItemStyle.Rect: A standard rectangular pressed selection.
    • @style/SelectableItemStyle.Rect.Colored: A colored rectangular pressed selection.
    • @style/SelectableItemStyle.RoundedRect: A rounded rectangular pressed selection.
    • @style/SelectableItemStyle.RoundedRect.Colored: A colored rounded rectangular pressed selection.
    <LinearLayout
        style="@style/SelectableItemStyle.Rect"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical"
        android:orientation="horizontal">
    
        <ImageView
            android:layout_width="42dp"
            android:layout_height="42dp"
            android:adjustViewBounds="true"
            android:src="@mipmap/ic_launcher"/>
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Green Theme"/>
    </LinearLayout>
  8. Configure Text Fields with TextInputLayout

    master

    For Material-style text input, wrap a TextInputEditText inside a TextInputLayout from the design support library:

    1. TextInputLayout uses @style/Widget.Design.TextInputLayout (default) to set the label text color to colorAccent.
    2. TextInputEditText uses @style/Widget.AppCompat.EditText (default) to set control colors to colorAccent when activated.
    <android.support.design.widget.TextInputLayout
    	android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	android:hint="Green Theme">
    	
    	<android.support.design.widget.TextInputEditText
    	    android:layout_width="match_parent"
    	    android:layout_height="wrap_content"/>
    </android.support.design.widget.TextInputLayout>
  9. Configure Floating Action Buttons (FAB)

    master

    Use the FloatingActionButton from the design support library. By default, it uses @style/Widget.Design.FloatingActionButton, which sets the button color to colorAccent and uses colorControlHighlight for interaction states.

    <android.support.design.widget.FloatingActionButton
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:src="@drawable/ic_palette"/>
  10. Tint Icons and Images

    master

    To tint an icon to a theme color, use the android:tint attribute with a theme attribute reference like ?colorAccent. For programmatic tinting, use DrawableCompat.setTint().

    <ImageView
        android:layout_width="36dp"
        android:layout_height="36dp"
        android:adjustViewBounds="true"
        android:src="@drawable/ic_palette"
        android:tint="?colorAccent"/>
  11. Configure Button styles

    master

    AppCompat provides several button styles to control color behavior:

    • Default: Use @style/Widget.AppCompat.Button. It uses colorButtonNormal for the background and colorControlHighlight as an overlay for pressed/focused states.
    • Colored: Use @style/Widget.AppCompat.Button.Colored. It uses colorAccent for the background.
    • Borderless: Use @style/Widget.AppCompat.Button.Borderless. It has no background and uses colorControlHighlight for interaction states.
    • Borderless Colored: Use @style/Widget.AppCompat.Button.Borderless.Colored. It uses colorAccent for the text color.
    <!-- Default Button -->
    <Button
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:text="Green Theme"/>
    
    <!-- Colored Button -->
    <Button
    	style="@style/Widget.AppCompat.Button.Colored"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:text="Green Theme"/>
    
    <!-- Borderless Button -->
    <Button
    	style="@style/Widget.AppCompat.Button.Borderless"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:text="Green Theme"/>
    
    <!-- Borderless Colored Button -->
    <Button
    	style="@style/Widget.AppCompat.Button.Borderless.Colored"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:text="Green Theme"/>
  12. Configure Spinners, SeekBars, and Progress Indicators

    master

    Standard controls for selection and progress:

    • Spinner: Use @style/Widget.AppCompat.Spinner or @style/Widget.AppCompat.Spinner.Underlined. The underline color is set to colorAccent when activated.
    • SeekBar: Uses @style/Widget.AppCompat.SeekBar (default). It uses colorAccent for the active track, colorControlNormal for the unset area, and colorControlHighlight for interaction.
    • ProgressBar: Uses @style/Widget.AppCompat.ProgressBar (default) or @style/Widget.AppCompat.ProgressBar.Horizontal. The progress color is set to colorAccent.
    <!-- Underlined Spinner -->
    <Spinner
        style="@style/Widget.AppCompat.Spinner.Underlined"
    	android:layout_width="match_parent"
    	android:layout_height="wrap_content"
    	android:spinnerMode="dropdown"/>
    
    <!-- SeekBar -->
    <SeekBar
    	android:layout_width="match_parent"
    	android:layout_height="wrap_content"/>
    
    <!-- Horizontal ProgressBar -->
    <ProgressBar
        style="@style/Widget.AppCompat.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:indeterminate="true"/>