I have an app I am writing and it is already contains a lot of code, I decided I want to add a navigation drawer to the main activity toolbar but I don\'t know how to do it with
The easiest way for you would be using this library.
Its really easy to implement and its very flexible.
If you want to do it yourself, consider reading official docs about creating navigation drawer.
I've tried the MaterialDrawer library, as suggested by @yury-dombaev and I have to admit it's far easier to implement than the official Navigation Drawer.
It's possible to implement either with Android X dependencies or with the normal ones.
In my case, since I have the normal ones, I've to stick with the MaterialDrawer 6.0.9v. Although there's a migration guide that I'll give a look.
To implement the library within your current activity do the following:
onCreate
() method of your Activity
: new DrawerBuilder().withActivity(this).build();
.Create a layout layout_left_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/bgLeftMenu">
<ImageView android:id="@+id/header"
android:src="@drawable/ic_launcher"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginTop="26dp"
android:layout_marginBottom="8dp"
android:layout_marginLeft="30dp"
android:layout_marginStart="40dp"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginTop="26dp"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@id/header">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerInParent="true">
<TextView
android:id="@+id/userName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textColor="@color/pressed"/>
<TextView
android:id="@+id/userEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:layout_below="@id/userName"
android:layout_centerInParent="true"
android:textColor="@color/pressed"
android:visibility="gone"/>
</LinearLayout>
</RelativeLayout>
<ListView android:id="@+id/menu_items_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/header"
android:dividerHeight="0dp"
android:divider="@null"
android:background="@color/bgLeftMenu"/>
<ProgressBar android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"/>
</RelativeLayout>
Inflate it in a Custom View:
public class SimpleLeftMenuView extends NavigationView {
private LayoutInflater mInflater;
private Context mContext;
private ListView mItemsList;
private MenuItemsAdapter mItemsAdapter;
private ProgressBar mProgress;
private OnClickMenu mListener;
private ImageView mHeader;
private TextView userName;
private TextView userEmail;
//region Constructors
public SimpleLeftMenuView(Context context) {
super(context);
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
initLayout();
setData();
}
public SimpleLeftMenuView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
initLayout();
setData();
}
public SimpleLeftMenuView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
initLayout();
setData();
}
//endregion
private void initLayout(){
mInflater.inflate(R.layout.layout_left_menu, this);
mItemsList = (ListView) findViewById(R.id.menu_items_list);
mProgress = (ProgressBar) findViewById(R.id.progress);
mHeader = (ImageView) findViewById(R.id.header);
userName = (TextView) findViewById(R.id.userName);
userEmail = (TextView) findViewById(R.id.userEmail);
mHeader.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// do something
}
});
}
public void setSelectedSection(String idSection) {
mItemsAdapter.setLastSelectedSection(idSection);
}
public void setmListener(OnClickMenu mListener) {
this.mListener = mListener;
}
private void setData() {
List<String> sections = new ArrayList<>();
sections.add(mContext.getString(R.string.home_id));
sections.add(mContext.getString(R.string.login_id));
sections.add(mContext.getString(R.string.settings_id));
//.........
//sections.add(mContext.getString(R.string.exit_id));
mItemsAdapter = new MenuItemsAdapter(mContext, sections, new OnClickMenu() {
@Override
public void onClick(String id) {
mItemsAdapter.setLastSelectedSection(id);
if (mListener != null)
mListener.onClick(id);
}
});
mItemsList.setAdapter(mItemsAdapter);
mItemsList.setSelection(0);
mItemsList.setItemChecked(0, true);
}
}
You have to create the MenuItemAdapter.
public class MenuItemsAdapter extends BaseAdapter {
private Context mContext;
private static String lastSelectedSection;
private List<String> mSections;
private int currentTextcolor;
private OnClickMenu mListener;
public MenuItemsAdapter(Context context, List<String> sections, OnClickMenu listener) {
mContext = context;
mSections = sections;
mListener = listener;
lastSelectedSection = sections.get(0);
}
@Override
public int getCount() {
return mSections.size();
}
@Override
public String getItem(int position) {
return mSections.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
return getCustomView(position, convertView, parent);
}
public View getCustomView(final int position, View convertView, ViewGroup parent) {
final MenuItemHolder holder;
if (convertView==null){
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(R.layout.layout_left_menu_item, parent, false);
holder = new MenuItemHolder(convertView);
convertView.setTag(holder);
}else {
holder = (MenuItemHolder) convertView.getTag();
}
Resources r = mContext.getResources();
int pxMarginSection = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, r.getDisplayMetrics());
holder.position = position;
holder.mLine.setVisibility(View.GONE);
holder.mTitle.setTextColor(mContext.getResources().getColor(R.color.primary));
holder.mIconView.setColorFilter(mContext.getResources().getColor(R.color.primary));
if (mSections.get(position).equals(mContext.getString(R.string.login_id))) {
holder.mIconView.setImageResource(R.drawable.ic_login_gp);
// holder.mIconView.setColorFilter(mContext.getResources().getColor(R.color.primary));
holder.mTitle.setText(mContext.getString(R.string.action_login));
holder.mLine.setVisibility(View.VISIBLE);
holder.mLayoutItem.setPadding(0, pxMarginSection, 0, pxMarginSection);
} else if (mSections.get(position).equals(mContext.getString(R.string.settings_id))) {
holder.mIconView.setImageResource(R.drawable.option);
holder.mTitle.setText(mContext.getString(R.string.action_settings));
holder.mLayoutItem.setPadding(0, pxMarginSection, 0, pxMarginSection);
holder.mLine.setVisibility(View.VISIBLE);
} else if (mSections.get(position).equals(mContext.getString(R.string.exit_id))) {
holder.mIconView.setImageResource(R.drawable.shutdown);
holder.mTitle.setText(mContext.getString(R.string.salir));
holder.mLayoutItem.setPadding(0, pxMarginSection, 0, pxMarginSection);
holder.mLine.setVisibility(View.VISIBLE);
}
holder.mLayoutItem.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getActionMasked()){
case MotionEvent.ACTION_DOWN:
currentTextcolor = holder.mTitle.getCurrentTextColor();
holder.mLayoutItemSelect.setBackgroundColor(mContext.getResources().getColor(R.color.primary));
holder.mTitle.setTextColor(mContext.getResources().getColor(R.color.text_info));
holder.mIconView.setColorFilter(mContext.getResources().getColor(R.color.text_info));
return true;
case MotionEvent.ACTION_UP:
holder.mLayoutItemSelect.setBackgroundResource(R.color.bgLeftMenu);
holder.mTitle.setTextColor(currentTextcolor);
holder.mIconView.setColorFilter(mContext.getResources().getColor(R.color.primary));
mListener.onClick(mSections.get(position));
return true;
case MotionEvent.ACTION_CANCEL:
holder.mLayoutItemSelect.setBackgroundColor(mContext.getResources().getColor(R.color.bgLeftMenu));
holder.mTitle.setTextColor(currentTextcolor);
holder.mIconView.setColorFilter(mContext.getResources().getColor(R.color.primary));
return true;
}
return false;
}
});
return convertView;
}
class MenuItemHolder {
// butterKnife
View view;
@Bind(R.id.title)
TextView mTitle;
@Bind(R.id.icon)
ImageView mIconView;
@Bind(R.id.layoutItem)
LinearLayout mLayoutItem;
@Bind (R.id.rl_line)
View mLine;
@Bind(R.id.layoutItemSelect)
LinearLayout mLayoutItemSelect;
int position;
public MenuItemHolder(View itemView) {
ButterKnife.bind(this, itemView);
view = itemView;
}
}
public void setLastSelectedSection(String idSection) {
lastSelectedSection = idSection;
}
}
Now you have to modify your current Activity:
Change your main activity layout to use DrawerLayout and add your custom view "SimpleLeftMenuView":
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#EDEDED">
// YOUR CURRENT LAYOUT
<yourpackage.custom.SimpleLeftMenuView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@color/bgLeftMenu"/>
</android.support.v4.widget.DrawerLayout>
Activity class:
Add global variables:
protected @Bind(R.id.navigation_view) SimpleLeftMenuView mLeftMenuView;
protected @Bind(R.id.drawerLayout) DrawerLayout mDrawerLayout;
Set onclick listener. You can do an actions depends on the id:
mLeftMenuView.setmListener(new OnClickMenu() {
@Override
public void onClick(String id) {
Log.d("MENU", "ic_menu_hamburger clicked: " + id);
closeDrawer(null);
if (id.equals(getString(R.string.settings_id))) {
Intent intent = new Intent(MainActivity.this,
SettingsActivity.class);
MainActivity.this.startActivity(intent);
} else if (id.equals(getString(R.string.exit_id))) {
// salir
showRateDialogBeforeExit();
}
}
});
I have created my own interface OnClickMenu:
public interface OnClickMenu {
void onClick(String id);
}
And add action to open drawer from menu icon:
@Override
public void onBackPressed() {
if((mDrawerLayout) != null && (mDrawerLayout.isDrawerOpen(GravityCompat.START)))
closeDrawer(null);
else {
super.onBackPressed();
}
}
public void closeDrawer(DrawerLayout.DrawerListener listener) {
mDrawerLayout.setDrawerListener(listener);
mDrawerLayout.closeDrawers();
}
public void openDrawer() {
mDrawerLayout.setDrawerListener(null);
mDrawerLayout.openDrawer(GravityCompat.START);
}
Menu:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_home, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
openDrawer();
return true;
}
return super.onOptionsItemSelected(item);
}
add to app build.gradle
compile 'com.android.support:design:26.0.0'
compile 'com.jakewharton:butterknife:8.6.0'
Change all @Bind to @BindView