Androidhive - Info-Android Getting Started With Material Design
Androidhive - Info-Android Getting Started With Material Design
info
http://www.androidhive.info/2015/04/android-getting-started-with-material-design/
You might have heard of android Material Design which was introduced in Android Lollipop version. In Material Design lot of new
things were introduced like Material Theme, new widgets, custom shadows, vector drawables and custom animations. If
you havent working on Material Design yet, this article will give you a good start.
In this tutorial we are going to learn the basic steps of Material Design development i.e writing the custom theme and
implementing the navigation drawer using the RecyclerView.
Go through the below links to get more knowledge over Material Design.
> Material Design Specifications
> Creating Apps with Material Design
DOWNLOAD CODE
You can go through this material design color patterns and choose the one that suits your app.
strings.xml
<resources>
<string name="app_name">Material Design</string>
<string name="action_settings">Settings</string>
<string name="action_search">Search</string>
<string name="drawer_open">Open</string>
<string name="drawer_close">Close</string>
<string name="nav_item_home">Home</string>
<string name="nav_item_friends">Friends</string>
<string name="nav_item_notifications">Messages</string>
<string-array name="nav_drawer_labels">
<item>@string/nav_item_home</item>
<item>@string/nav_item_friends</item>
<item>@string/nav_item_notifications</item>
</string-array>
<string name="title_messages">Messages</string>
<string name="title_friends">Friends</string>
<string name="title_home">Home</string>
</resources>
3. Open res values colors.xml and add the below color values. If you dont find colors.xml, create a new resource file with
the name.
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#F50057</color>
<color name="colorPrimaryDark">#C51162</color>
<color name="textColorPrimary">#FFFFFF</color>
<color name="windowBackground">#FFFFFF</color>
<color name="navigationBarColor">#000000</color>
<color name="colorAccent">#FF80AB</color>
</resources>
4. Open res values dimens.xml and add below dimensions.
dimens.xml
<resources>
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="nav_drawer_width">260dp</dimen>
</resources>
5. Open styles.xml under res values and add below styles. The styles defined in this styles.xml are common to all the android
versions. Here I am naming my theme as MyMaterialTheme.
styles.xml
<resources>
</style>
</resources>
6. Now under res, create a folder named values-v21. Inside values-v21, create another styles.xml with the below styles. These
styles are specific to Android Lollipop only.
styles.xml
<resources>
</resources>
7. Now we have the basic Material Design styles ready. In order to apply the theme, open AndroidManifest.xml and modify the
android:theme attribute of tag.
android:theme="@style/MyMaterialTheme"
So after applying the theme, your AndroidManifest.xml should look like below.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="info.androidhive.materialdesign" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/MyMaterialTheme" >
<activity
android:name=".activity.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</manifest>
Now if you run the app, you can see the notification bar color changed to the color that we have mentioned in our styles.
8. Create an xml file named toolbar.xml under res layout and add android.support.v7.widget.Toolbar element. This create the
toolbar with specific height and theming.
toolbar.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
local:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
local:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
9. Open the layout file of your main activity (activity_main.xml) and add the toolbar using tag.
activity_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=".MainActivity">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:orientation="vertical">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
</LinearLayout>
</RelativeLayout>
Run the app and see if the toolbar displayed on the screen or not.
Now lets try to add a toolbar title and enable the action items.
10. Download this search icon and import it into Android Studio as a Image Asset.
11. To import the Image Asset in Android Studio, right click on res New Image Asset . It will show you a popup window to
import the resource. Browse the search icon that you have downloaded in the above step, select Action Bar and Tab Icons for
Asset Type and give the resource name as ic_search_action and proceed.
12. Once the icon is imported, open menu_main.xml located under res menu and add the search menu item as mentioned
below.
13. Now open your MainActivity.java and do the below changes.
> Extend the activity from AppCompatActivity
> Enable the toolbar by calling setSupportActionBar() by passing the toolbar object.
> Override onCreateOptionsMenu() and onOptionsItemSelected() methods to enable toolbar action items.
MainActivity.java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
After doing the above changes, if you run the app, you should see the search icon and action overflow icon.
NavDrawerItem.java
package info.androidhive.materialdesign.model;
/**
* Created by Ravi on 29/07/15.
*/
public class NavDrawerItem {
private boolean showNotify;
private String title;
public NavDrawerItem() {
<TextView
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="30dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textSize="15dp"
android:textStyle="bold" />
</RelativeLayout>
18. Download this profile icon and paste it in your drawable folder. This step is optional, but this icon used in the navigation
drawer header part.
19. Create another xml layout named fragment_navigation_drawer.xml and add the below code. This layout renders the
complete navigation drawer view. This layout contains a header section to display the user information and a RecyclerView to
display the list view.
fragment_navigation_drawer.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
<RelativeLayout
android:id="@+id/nav_header_container"
android:layout_width="match_parent"
android:layout_height="140dp"
android:layout_alignParentTop="true"
android:background="@color/colorPrimary">
<ImageView
android:layout_width="70dp"
android:layout_height="70dp"
android:src="@drawable/ic_profile"
android:scaleType="fitCenter"
android:layout_centerInParent="true" />
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/drawerList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/nav_header_container"
android:layout_marginTop="15dp" />
</RelativeLayout>
20. As the RecyclerView is customized, we need an adapter class to render the custom xml layout. So under adapter package,
create a class named NavigationDrawerAdapter.java and paste the below code. This adapter class inflates
nav_drawer_row.xml and renders the RecycleView drawer menu.
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.Collections;
import java.util.List;
/**
* Created by Ravi Tamada on 12-03-2015.
*/
public class NavigationDrawerAdapter extends
RecyclerView.Adapter<NavigationDrawerAdapter.MyViewHolder> {
List<NavDrawerItem> data = Collections.emptyList();
private LayoutInflater inflater;
private Context context;
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.nav_drawer_row, parent, false);
MyViewHolder holder = new MyViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
NavDrawerItem current = data.get(position);
holder.title.setText(current.getTitle());
@Override
public int getItemCount() {
return data.size();
}
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import info.androidhive.materialdesign.R;
import info.androidhive.materialdesign.adapter.NavigationDrawerAdapter;
import info.androidhive.materialdesign.model.NavDrawerItem;
public FragmentDrawer() {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
titles = getActivity().getResources().getStringArray(R.array.nav_drawer_labels);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@Override
public void onLongClick(View view, int position) {
}
}));
return layout;
}
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
getActivity().invalidateOptionsMenu();
}
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
toolbar.setAlpha(1 - slideOffset / 2);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerLayout.post(new Runnable() {
@Override
public void run() {
mDrawerToggle.syncState();
}
});
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child,
recyclerView.getChildPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
@Override
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/container_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar" />
</LinearLayout>
<FrameLayout
android:id="@+id/container_body"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
<fragment
android:id="@+id/fragment_navigation_drawer"
android:name="info.androidhive.materialdesign.activity.FragmentDrawer"
android:layout_width="@dimen/nav_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
app:layout="@layout/fragment_navigation_drawer"
tools:layout="@layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
Now we have all the layout files and java classes ready in place. Lets do the necessary changes in MainActivity to make the
navigation drawer functioning.
23. Open your MainActivity.java and do the below changes.
> Implement the activity from FragmentDrawer.FragmentDrawerListener and add the onDrawerItemSelected() override
method.
> Create an instance of FragmentDrawer and set the drawer selected listeners.
MainActivity.java
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (FragmentDrawer)
getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout)
findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDrawerItemSelected(View view, int position) {
}
}
Now if you run the app, you can see the navigation drawer with a header and few list items in it.
fragment_home.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"
android:orientation="vertical"
tools:context="info.androidhive.materialdesign.activity.HomeFragment">
<TextView
android:id="@+id/label"
android:layout_alignParentTop="true"
android:layout_marginTop="100dp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="45dp"
android:text="HOME"
android:textStyle="bold"/>
<TextView
android:layout_below="@id/label"
android:layout_centerInParent="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="12dp"
android:layout_marginTop="10dp"
android:gravity="center_horizontal"
android:text="Edit fragment_home.xml to change the appearance" />
</RelativeLayout>
25. Under activity package, create a fragment class named HomeFragment.java and add below code.
HomeFragment.java
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public HomeFragment() {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container,
false);
return rootView;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@Override
public void onDetach() {
super.onDetach();
}
}
26. Create two more fragment classes named FriendsFragment.java, MessagesFragment.java and respected layout files
named fragment_friends.xml and fragment_messages.xml and add the code from above two steps.
27. Now open MainActivity.java and do the below changes. In the below code
> displayView() method displays the fragment view respected the navigation menu item selection. This method should be called
in onDrawerItemSelected() to render the respected view when a navigation menu item is selected.
MainActivity.java
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (FragmentDrawer)
getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout)
findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
displayView(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
if(id == R.id.action_search){
Toast.makeText(getApplicationContext(), "Search action is selected!",
Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.commit();
getSupportActionBar().setTitle(title);
}
}
}
Now if you run the app, you can see the selection of navigation drawer menu is working and respected view displayed below the
toolbar.
Whats Next?
Below are few more material components you can add to your app. These were implemented using recent Android Design
Support Library.
Learn how floating labels works on EditText with a simple form validation example.
4. Snackbar
Add the Snackbar to your app to give immediate feedback about any operation that user performed.
Change Log
Updated On