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'