Building Material Design App Using Android Design Support Library and AppCompat Theme

get-location
Android Design Support Library brings a number of material design components that are compatiable with all Android 2.1 or higher devices. The new componenets are navigation view view, TextInputLayout for floating labels for editing text, a floating action button, snackbar, tabs, coordinatorLayout, AppBarLayout & Collapsing Toolbars. In this post we will create an app that follows material design specifications using the new components provided by Design Support Library. .

Environment & Tools

  • Windows 7
  • Eclipse ADT
  • Nexus 5
  • Android SDK v22 or higher
  • Android Build Tools v22.0.1 or higher
  • Android Support Library, revision 22.2.0 or higher

About this Sample App

The code below is for a dummy app that will show how to use:

  • Toolbar
  • FloatActionButton
  • Snackbar
  • Tabs
  • CoordinatorLayout
    • CoordinatorLayout with (FloatActionButton & Snackbar)
    • CoordinatorLayout with AppBarLayout
  • CollapsingToolbarLayout
  • NavigationView

Pre

I. Create new Android Project

  • Application Name: HMKCODE App
  • Project Name: android-material-design-appcompat
  • Package Name: com.hmkcode.app

II. Import Library

  • Import android support library v7 appcompat.
  • Import android design support library.
  • Import cardview library

III. Create Color Palette

Read Customize the Color for more details.

/res/values/colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>    
    <color name="window_background">#CC000000</color>
    
        
    <color name="my_primary">#ED1C24</color>
    <color name="my_primary_dark">#CC0000</color>
    <color name="my_primary_light">#B3E5FC</color>
    <color name="my_accent">#FF5722</color>
    <color name="my_primary_text">#ffffff</color>
    <color name="my_secondary_text">#ffffff</color>
    <color name="my_icons">#FFFFFF</color>
    <color name="my_divider">#B6B6B6</color>
</resources>

( 1 ) Toolbar

Toolbar

  • Toolbar was added in revision 21 of Android Support Library (October 2014)
  • Toolbar generalizes the functionality of ActionBar for use within app layouts
  • Add Toolbar view to activity_main.xml

res/layout/activiyt_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.hmkcode.app.MainActivity">

    
    <android.support.v7.widget.Toolbar
         android:id="@+id/toolbar"
         android:layout_width="match_parent"
         android:layout_height="?attr/actionBarSize"
         android:background="?attr/colorPrimary"/>

</RelativeLayout>
  • To use Toolbar as an Action Bar, first disable the decor-provided Action Bar in values/styles.xml.
  • To disable the decor-provided Action Bar, extend Theme.AppCompat.NoActionBar (or its light variant).

res/values/styles.xml

<resources>
 
    <style name="Base.Theme.HMKCodeApp" parent="Theme.AppCompat.NoActionBar">
        
        <item name="colorPrimary">@color/my_primary</item>
       
        <!--   darker variant for the status bar and contextual app bars -->
        <item name="colorPrimaryDark">@color/my_primary_dark</item>
        
        <!--   theme UI controls like checkboxes and text fields e.g. FloatActionButton -->
        <item name="colorAccent">@color/my_accent</item>

        <!-- Title Text Color -->
        <item name="android:textColorPrimary">@color/my_primary_text</item> 
        
        <!-- color of the menu overflow icon (three vertical dots) -->
        <item name="android:textColorSecondary">@color/my_secondary_text</item>  
        
        
       <item name="android:windowBackground">@color/window_background</item> 
    </style>
    
     <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
     <style name="AppBaseTheme" parent="Base.Theme.HMKCodeAppm">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>
    
    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
    </style>

</resources>
  • In MainActivity.java setSupportActionBar(toolbar);
  • And show menu icon "icon on the left".
  • Create a new method setupToolbar() and call it from onCreate().
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        setupToolbar();
        
    }

    private void setupToolbar(){
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    // Show menu icon
        final ActionBar ab = getSupportActionBar();
        ab.setHomeAsUpIndicator(R.drawable.ic_menu);
        ab.setDisplayHomeAsUpEnabled(true);
    }
}
  • To show action item as an icon on the toolbar define menu item as following

/res/menu/main.xml

<item
 android:id="@+id/action_find_location"
 android:orderInCategory="101"
 android:title="@string/action_find_location"
 android:icon="@drawable/ic_action_location_found"
 app:showAsAction="always"/>

( 2 ) FloatActionButton

floatactionbutton

  • FloatingActionButton is a round button for a primary action on your interface.
  • The color of this button is set in colorAccent from your theme.

/res/layout/activity_main.xml

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

    
    <android.support.v7.widget.Toolbar
         android:id="@+id/toolbar"
         android:layout_width="match_parent"
         android:layout_height="?attr/actionBarSize"
         android:background="?attr/colorPrimary"/>

    
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_action_location_found"
        android:layout_marginBottom="20dp"
        android:layout_marginRight="20dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        app:fabSize="normal" />
</RelativeLayout>

( 3 ) Snackbar

floatactionbutton

  • Like Toast, Snackbar provides lightweight, quick feedback about some operation.
  • Snackbar shows up on the bottom of the screen and contain text with an optional single action.
  • Snackbar automatically dismiss after the given time length by animating off the screen.
  • Also, users can swipe them away before the timeout.
  • Here we will show Snackbar when user click on the float action button.
  • Note in the image above the snackbar is hiding the float action button, we will resolve this later.
public class MainActivity extends AppCompatActivity 
        implements OnClickListener {

    FloatingActionButton fab;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_2);
        
        setupFab();
        setupToolbar();
        
    }

    private void setupFab(){
        fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(this);
    }
    private void setupToolbar(){
        ...
    }

    @Override
    public void onClick(View view) {
        
        if(view.getId() == R.id.fab){
            
            Snackbar
              .make(findViewById(R.id.rootLayout), 
                "This is Snackbar", 
                Snackbar.LENGTH_LONG)
              .setAction("Action", this)
              .show(); // Do not forget to show!
        }
    }
}

( 4 ) Tablayout

tablayout

  • TabLayout implements both fixed tabs as well as scrollable tabs, where the tabs are not a uniform size and can scroll horizontally.
  • Tabs can be added programmatically:

MainActivity.java

public class MainActivity extends AppCompatActivity implements OnClickListener {

    FloatingActionButton fab;
    TabLayout tabLayout;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_4);
        
        setupToolbar();
        setupTablayout();
        setupFab();
        
    }
    
    private void setupTablayout(){
        
        tabLayout = (TabLayout) findViewById(R.id.tabLayout);
        tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
        tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab 2"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab 3"));
        tabLayout.addTab(tabLayout.newTab().setText("Tab 4"));
    }
}

/res/layout/activity_main.xml

<RelativeLayout ..>

    
        <android.support.v7.widget.Toolbar
             ../>
    
        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:scrollbars="horizontal"
            android:layout_below="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways" />
        

      <android.support.design.widget.FloatingActionButton
                    .. />
</RelativeLayout>

( 5 ) CoordinatorLayout

  • CoordinatorLayout provides additional level of control over touch events between child views.

CoordinatorLayout with FloatingActionButton & Snackbar

tablayout

  • CoordinatorLayout resolve the issue of snackbar displaying over the FloatingActionButton.
  • FloatingActionButton automatically moves upward as the snackbar animates in and returns to its position when the snackbar hides.
  • CoordinatorLayout enables user to swipe snackbar away before the timeout.

CoordinatorLayout with AppBarLayout

tablayout

  • AppBarLayout allows your Toolbar and other views (such as tabs provided by TabLayout) to react to scroll events in a sibling view.
  • the AppBarLayout can respond to those events by using the children’s scroll flags.
  • Toolbar reacts to scroll events in a sibling view app:layout_scrollFlags="scroll|enterAlways"
  • TabLayout remains pinned to the top of the screen while Toolbar view collapses.
  • includes a layout with CardView views

/res/layout/activity_main.xml

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/coordinatorLayout"
    android:layout_height="match_parent"
    android:layout_width="match_parent">
        
    
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">
          
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"/>
    
        <android.support.design.widget.TabLayout
            android:id="@+id/tabLayout"
            android:scrollbars="horizontal"
            android:layout_below="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary" />
    
    </android.support.design.widget.AppBarLayout>
    
     <!-- Your Scrollable View -->
    <include layout="@layout/cardviews"/>
    
    <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_action_location_found"
            android:layout_marginBottom="20dp"
            android:layout_marginRight="20dp"
            android:layout_gravity="bottom|right"
            app:fabSize="normal" />
    
</android.support.design.widget.CoordinatorLayout>

( 6 ) CollapsingToolbarLayout

tablayout

  • CollapsingToolbarLayout to ensure that the Toolbar itself remains pinned to the top of the screen while the view collapses.
  • Toolbar title will automatically appear larger when the layout is fully visible, then transition to its default size as it is collapsed.
  • Note that in those cases, you should call *setTitle()** on the CollapsingToolbarLayout, rather than on the Toolbar itself*.
<android.support.design.widget.CoordinatorLayout
    . . . >
        
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/detail_backdrop_height"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
         
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            
       <ImageView
                android:id="@+id/backdrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax" />
          
        <android.support.v7.widget.Toolbar
             android:id="@+id/toolbar"
             android:layout_width="match_parent"
             android:layout_height="?attr/actionBarSize"
             android:background="?attr/colorPrimary"
             app:layout_collapseMode="pin"/>
    
    
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>
    
     <!-- Your Scrollable View -->
    <include layout="@layout/cardviews"/>
    
    <android.support.design.widget.FloatingActionButton
                android:id="@+id/fab"
                . . . />
    
</android.support.design.widget.CoordinatorLayout>

( 7 ) NavigationView

tablayout

  • NavigationView makes adding navigation drawer to your app easier than before.
  • You can nflate your navigation items through a menu resource.
  • NavigationView should go inside DrawerLayout.
  • app:headerLayout attribute controls the (optional) layout used for the header.
  • app:menu attribute is the menu resource for the navigation items (which can also be updated at runtime).

/res/layout/activity_main.xml

<android.support.v4.widget.DrawerLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     ....>
     
    <android.support.design.widget.CoordinatorLayout >
    ....
    </android.support.design.widget.CoordinatorLayout>
    
    <android.support.design.widget.NavigationView
         android:id="@+id/navigation"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_gravity="start"
         app:headerLayout="@layout/nav_header"
         app:itemTextColor="#333"
         app:itemIconTint="#333"
         app:menu="@menu/navigation_drawer_items" />
         
</android.support.v4.widget.DrawerLayout>

/res/layout/nav_header.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="192dp"
    android:background="?attr/colorPrimaryDark"
    android:padding="16dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"
    android:orientation="vertical"
    android:gravity="bottom">

    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="HMKCODE App"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

</LinearLayout>

/res/menu/navigationdraweritems

<menu 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"
    tools:context="com.hmkcode.mongoz.MainActivity" >

    <group android:checkableBehavior="all">
        <item
            android:id="@+id/navigation_item_1"
            android:icon="@drawable/ic_action_location_found_dark"
            android:title="Toolbar"/>
        <item
            android:id="@+id/navigation_item_2"
            android:icon="@drawable/ic_action_location_found_dark"
            android:title="FloatActionButton"/>
        
        <item
            android:id="@+id/navigation_item_3"
            android:icon="@drawable/ic_action_location_found_dark"
            android:title="NavigationView"/>
    </group>

</menu>

MainActivity.java

public class MainActivity extends AppCompatActivity implements OnClickListener {

    DrawerLayout drawerLayout;
    CollapsingToolbarLayout collapsingToolbarLayout;
    Toolbar toolbar;
    TabLayout tabLayout;
    FloatingActionButton fab;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        setupNavigationView();
        setupToolbar();
        setupTablayout();
        setupCollapsingToolbarLayout();
        setupFab();

    }
    
    private void setupNavigationView(){
        
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                drawerLayout.openDrawer(GravityCompat.START);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    ...
}

Source Code @ GitHub