In Material Design, it's layout be come more flexible with animations and developers can customizing it's easily with our own styles. For example, this is toggle menu animation:
In this post, I will make a NavigationDrawer with Toolbar in a simple project. By this, you can deep understanding the way how to implement it.
In this post, I will make a NavigationDrawer with Toolbar in a simple project. By this, you can deep understanding the way how to implement it.
Create main activity layout
So, we have a simple activity layout below:
Note: In this layout, I put Toolbar inside DrawerLayout, so this NavigationDrawer will occult Toolbar when it's appear:
If you want it appear below Toolbar, please include Toolbar layout outside DrawerLayout and output will be like this:
Making Sliding Panel
Create a model (Java object):
package devexchanges.info.navigationdrawer;
/**
* Created by Hong Thai.
*/
public class SocialNetwork {
private int imageId;
private int bigImageId;
private String name;
private String country;
public SocialNetwork(int imageId, int bigImageId, String name, String country) {
this.country = country;
this.bigImageId = bigImageId;
this.imageId = imageId;
this.name = name;
}
public int getImageId() {
return imageId;
}
public int getBigImageId() {
return bigImageId;
}
public String getCountry() {
return country;
}
public String getName() {
return name;
}
}
Now, we create a customizing a ListView adapter extends from ArrayAdapter<T>, in this, I use a ViewHolder class to make it's view more smoothly. Source code for adapter:package devexchanges.info.navigationdrawer;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import devexchanges.info.materialdesignnavigationdrawer.R;
public class ListViewAdapter extends ArrayAdapter<Socialnetwork> {
private MainActivity activity;
private ArrayList<Socialnetwork> socialNetworks;
public ListViewAdapter(MainActivity activity, int resource, ArrayList<Socialnetwork> objects) {
super(activity, resource, objects);
this.activity = activity;
this.socialNetworks = objects;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
LayoutInflater inflater = (LayoutInflater) activity
.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
// If holder not exist then locate all view from UI file.
if (convertView == null) {
// inflate UI from XML file
convertView = inflater.inflate(R.layout.item_listview, parent, false);
// get all UI view
holder = new ViewHolder(convertView);
// set tag for holder
convertView.setTag(holder);
} else {
// if holder created, get tag from view
holder = (ViewHolder) convertView.getTag();
}
holder.name.setText(getItem(position).getName());
holder.icon.setImageResource(getItem(position).getImageId());
//handling each item on click
//update main layout by this action
convertView.setOnClickListener(onClickListener(position));
return convertView;
}
private View.OnClickListener onClickListener(final int position) {
return new View.OnClickListener() {
@Override
public void onClick(View v) {
activity.updateMainLayout(getItem(position));
}
};
}
private class ViewHolder {
private ImageView icon;
private TextView name;
public ViewHolder(View v) {
icon = (ImageView) v.findViewById(R.id.icon);
name = (TextView) v.findViewById(R.id.name);
}
}
}
In activity, set adapter for ListView when initializing Sliding Panel. Set a listener to be notified of drawer events though initDrawerlayout() method and call it in onCreate():private void initDrawerLayout() {
setListViewData();
setListViewHeader();
//Mount listview with adapter
adapter = new ListViewAdapter(this, R.layout.item_listview, socialNetworks);
listView.setAdapter(adapter);
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
R.string.drawer_open, R.string.drawer_close) {
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
drawerLayout.setDrawerListener(drawerToggle);
}
After that, synchronize the state of the drawer indicator/affordance with the linked DrawerLayout by invoke syncState(). I overrided onPostCreate() and onConfigurationChanged() methods:@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
We also add a header for ListView to make our Sliding Panel more beautiful (like GooglePlus app): private void setListViewHeader() {
LayoutInflater inflater = getLayoutInflater();
View header = inflater.inflate(R.layout.header_listview, listView, false);
listView.addHeaderView(header, null, false);
}
Coding Main Layout
/**
* Replace fragment to Main layout
* @param socialNetwork
*/
public void updateMainLayout(SocialNetwork socialNetwork) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, ContentFragment.newInstance(socialNetwork));
transaction.commit();
//close navigation drawer after replace fragment
drawerLayout.closeDrawers();
}
And source for ContentFragment is simple. Put/get data by a Bundle object and update data to views by getArguments():package devexchanges.info.navigationdrawer;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import devexchanges.info.materialdesignnavigationdrawer.R;
public class ContentFragment extends Fragment {
private TextView socialNetworkName;
private TextView country;
private ImageView image;
public static ContentFragment newInstance(SocialNetwork nw) {
Bundle args = new Bundle();
ContentFragment fragment = new ContentFragment();
args.putString("SN_NAME", nw.getName());
args.putInt("SN_LOGO", nw.getBigImageId());
args.putString("SN_COUNTRY", nw.getCountry());
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_content, container, false);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
socialNetworkName = (TextView)view.findViewById(R.id.social_network);
country = (TextView)view.findViewById(R.id.country);
image = (ImageView)view.findViewById(R.id.icon);
updateData();
}
private void updateData() {
socialNetworkName.setText(getArguments().getString("SN_NAME"));
image.setImageResource(getArguments().getInt("SN_LOGO"));
country.setText(getArguments().getString("SN_COUNTRY"));
}
}
Coming here, we have complete our project core. This is full code of main activity (the most important file):package devexchanges.info.navigationdrawer;
import android.support.v4.app.FragmentTransaction;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.widget.ListView;
import java.util.ArrayList;
import devexchanges.info.materialdesignnavigationdrawer.R;
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private DrawerLayout drawerLayout;
private ActionBarDrawerToggle drawerToggle;
private ListView listView;
private ArrayList<Socialnetwork> socialNetworks;
private ListViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
socialNetworks = new ArrayList<>();
findViewById();
setSupportActionBar(toolbar);
initDrawerLayout();
}
private void findViewById() {
listView = (ListView) findViewById(R.id.list);
toolbar = (Toolbar) findViewById(R.id.toolbar);
drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
}
private void initDrawerLayout() {
setListViewData();
setListViewHeader();
//Mount listview with adapter
adapter = new ListViewAdapter(this, R.layout.item_listview, socialNetworks);
listView.setAdapter(adapter);
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar,
R.string.drawer_open, R.string.drawer_close) {
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
};
drawerLayout.setDrawerListener(drawerToggle);
}
private void setListViewHeader() {
LayoutInflater inflater = getLayoutInflater();
View header = inflater.inflate(R.layout.header_listview, listView, false);
listView.addHeaderView(header, null, false);
}
private void setListViewData() {
socialNetworks.add(new SocialNetwork(R.mipmap.zalo_small, R.mipmap.zalo_big, "Zalo", "VIETNAM"));
socialNetworks.add(new SocialNetwork(R.mipmap.fb_small, R.mipmap.fb_big, "Facebook", "USA"));
socialNetworks.add(new SocialNetwork(R.mipmap.tw_small, R.mipmap.tw_big, "Twitter", "USA"));
socialNetworks.add(new SocialNetwork(R.mipmap.pin_small, R.mipmap.pin_big, "Pinterest", "USA"));
socialNetworks.add(new SocialNetwork(R.mipmap.gp_small, R.mipmap.gp_big, "Google+", "USA"));
socialNetworks.add(new SocialNetwork(R.mipmap.baidu_small, R.mipmap.baidu_big, "Baidu", "CHINA"));
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToggle.onConfigurationChanged(newConfig);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
/**
* Replace fragment to Main layout
* @param socialNetwork
*/
public void updateMainLayout(SocialNetwork socialNetwork) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.container, ContentFragment.newInstance(socialNetwork));
transaction.commit();
//close navigation drawer after replace fragment
drawerLayout.closeDrawers();
}
}
Some necessary features/layouts
Layout for ListView header:
Customizing a theme based on "Theme.Appcompat.Light.NoActionBar" and apply for whole project:
Toolbar layout:
Colors resource:
Remember add support libraries dependency in your local build.gradle file:
compile 'com.android.support:appcompat-v7:22.2.0' compile 'com.android.support:support-v4:22.2.0'