I'm working on an Android app for an Engineering Design project that includes a drawer. One of my group members elected to use the android.support.design.widget.NavigationView API to do this, and it's been causing us some problems. Our MainActivity class implements onNavigationItemSelectedListener, which I understand acts as a listener for the items in the drawer and other navigation bars. The problem is, when one of these navigation items is selected, the onNavigationItemSelected method that has been implemented is not called (I know this because it's supposed to put out a message through LogCat if it is called). All the references I've found for this API suggest that I've done everything right so far, but I've apparently missed something, so any help is appreciated.
Here is the relevant code from the MainActivity class:
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpNavComponents();
setUpMapComponents();
PathfinderDataHandler handler = new PathfinderDataHandler();
}
private void setUpNavComponents()
{
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
navigationView.setNavigationItemSelectedListener(this);
}
private void setUpMapComponents()
{
mapFrag = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
mapFrag.getMapAsync(this);
}
#Override
public boolean onNavigationItemSelected(MenuItem item)
{
// Handle navigation view item clicks here.
int id = item.getItemId();
Log.d(null, "onNavigationItemSelected Called");
if (id == R.id.buildings)
{
// Handle the camera action
Log.d(null, "Buildings selected");
}
else if (id == R.id.blue_phones)
{
Log.d(null, "Blue Phones selected");
}
else if (id == R.id.bus_stops)
{
Log.d(null, "Bus Stops selected");
}
else if (id == R.id.pedways)
{
Log.d(null, "Pedways selected");
}
DrawerLayout drawer = findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
Here is the code from activity_main_drawer.xml (Which holds all the items for the drawer)
<?xml version="1.0" encoding="utf-8"?>
<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:showIn="navigation_view">
<group
android:checkableBehavior="all"
android:enabled="true">
<item
android:id="#+id/buildings"
android:title="#string/building_show_select"
app:actionLayout="#layout/switch_item"
app:showAsAction="always" />
<item
android:id="#+id/blue_phones"
android:title="#string/blue_phone_select"
app:actionLayout="#layout/switch_item"
app:showAsAction="always" />
<item
android:id="#+id/bus_stops"
android:title="#string/bus_stop_select"
app:actionLayout="#layout/switch_item"
app:showAsAction="always" />
<item
android:id="#+id/pedways"
android:title="#string/pedway_select"
app:actionLayout="#layout/switch_item"
app:showAsAction="always" />
</group>
Here is the code for activity_main.xml, which adds the activity_main_drawer to the NavigationView.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
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"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="visible" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
Another thing to note is that I'm using Switch items instead of regular Menu items.
And before anyone says anything, YES I know this API is depreciated and I should be using NavigationUI in AndroidX, but I don't have time to refactor the app so I have to make do with this.
You have to provide a non null tag for Log.d(String, String), else there will be nothing written to Logcat.
I tried with
Log.d(null, "HelloWorld");
Log.d("TEST", " HelloWorld");
and got only one line in Logcat:
Related
Can anyone please help me on designing this android layout? I want to put two icons on the drawer toolbar like on the image below.
This is LeftNavigationActivity.class
public class LeftNavigationActivity extends BaseActivity
implements NavigationView.OnNavigationItemSelectedListener {
private ImageView profilePic;
Session session;
FragmentManager fragmentManager = getSupportFragmentManager();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_left_navigation);
this.setTitle("Home");
session = new Session(this);
if (!session.loggedIn()) {
logOut();
}
View v = getLayoutInflater().inflate(R.layout.nav_header_left_navigation,
null);
TextView username = (TextView) v.findViewById(R.id.username);
Intent intent = getIntent();
String uname = intent.getStringExtra("username");
Toast.makeText(this, "Welcome " + uname, Toast.LENGTH_SHORT).show();
username.setText(uname);
LoansAndDebtsFragment loansAndDebtsFragment = new LoansAndDebtsFragment();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragment,
loansAndDebtsFragment, loansAndDebtsFragment.getTag()).commit();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView)
findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
FragmentManager fragmentManager = this.getSupportFragmentManager();
int stackCount = fragmentManager.getBackStackEntryCount();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else if (fragmentManager.getFragments() != null) {
LoansAndDebtsFragment loansAndDebtsFragment = new
LoansAndDebtsFragment();
fragmentManager.beginTransaction().replace(R.id.layout_for_fragment,
loansAndDebtsFragment, loansAndDebtsFragment.getTag()).commit();
}
}
The LeftNavigationActivity is the BaseDrawerActivity which contains the navigation menu.
This is app_bar_left_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.gebeya.jo.pyf.activities.LeftNavigationActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.NoToolBarWithABrandTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorWhite"
app:titleTextColor="#color/colorBrand1"
app:popupTheme="#style/AppTheme.NoToolBarWithABrandTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="#layout/content_left_navigation" />
</android.support.design.widget.CoordinatorLayout>
This is nav_header_left_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="190dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#drawable/nav_background"
android:orientation="vertical">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/profile_image"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="#drawable/eyasu"
android:layout_marginLeft="20dp"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
app:civ_border_color="#color/colorBrand1"
app:civ_border_width="4dp"
android:layout_alignParentStart="true"
android:paddingBottom="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="#string/userFullName"
android:textSize="14sp"
android:textColor="#FFF"
android:textStyle="bold"
android:gravity="left"
android:paddingBottom="4dp"
android:id="#+id/username"
android:layout_above="#+id/email"
android:layout_alignLeft="#+id/profile_image"
android:layout_alignStart="#+id/profile_image" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/email"
android:hint="#string/userEmail"
android:gravity="left"
android:layout_marginBottom="8dp"
android:textSize="14sp"
android:textColor="#fff"
android:layout_alignParentBottom="true"
android:layout_alignLeft="#+id/username"
android:layout_alignStart="#+id/username" />
</RelativeLayout>
Open Android Studio
Start a new Android Studio project
Select Navigation Drawer Activity
Pick your icons here: https://material.io/icons/
1. Create an menu XML with your desired menu items and put this XML into res/menu/ folder.
menu.xml:
<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.ferdous.advancefilter.MainActivity">
<item
android:id="#+id/action_notification"
android:title="Notification"
android:icon="#drawable/ic_action_notification"
app:showAsAction="always" />
<item
android:id="#+id/action_warning"
android:title="Notification"
android:icon="#drawable/ic_action_warning"
app:showAsAction="always" />
</menu>
2. In your Activity, override method onCreateOptionsMenu() to add menu items to Toolbar and override method onOptionsItemSelected() to handle the Toolbar item click event.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case R.id.action_notification:
// Do something
break;
case R.id.action_warning:
// Do something
break;
}
return super.onOptionsItemSelected(item);
}
OUTPUT:
#. If you want to add count badge over your menu item like below then you can follow my another answer Notification Badge On Action Item Android. I have added detail steps and codes.
Hope this will help~
I have written a piece of code as part of an app where I want to implement a back button on the action bar/tool bar such that when the button is pressed, the previous page (the page/fragment immediately before the current page/fragment) will be displayed.
This is the code for the ToolBar, DrawerLayout, NavigationView and getSupportActionBar():
final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
final NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setVisibility(View.VISIBLE);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setLogo(R.mipmap.ic_launcher);
getSupportActionBar().setDisplayUseLogoEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
I am unable to use ActionBar. For some reason (I don't know why), my Android studio/ program, will not allow me to use the ActionBar. So I am substituting that with the set/getSupportActionBar().
The function used in relation to this are:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_settings, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
My activity_main.xml file is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:id="#+id/activity_main"
android:orientation="vertical"
tools:openDrawer="start"
tools:context="com.example.albin.settings_menu.SettingsActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff">
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:title="Settings"/>
<android.support.v4.widget.DrawerLayout
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"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar">
</FrameLayout>
<android.support.design.widget.NavigationView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
android:layout_marginTop="-24dp"
app:menu="#menu/options_menu" />
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
</LinearLayout>
The problem is that I don't know which is the useful code, which is the useless code and how to mix/join/(add additional codes to) these (codes, methods, variables/objects, fragments, xml layouts) to get the desired outcome, that is, the application of a back button on the action bar/tool bar.
Most of the code above is implemented for the up button, not the back button. I have read at several places that up and back buttons are not the same.
I tried several links on internet as well as on this site, but none of them has just what I need.
Hope someone can give me an clear answer...
You can include the back icon in ToolBar:
Initialize ToolBar:
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
You can use an drawable icon as a back button.
toolbar.setNavigationIcon(R.drawable.your_drawable_icon);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// what do you want here
}
});
If you do not want to use drawable icon then:
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// what do you want here
}
});
Actually your layout having that issue because you have added toolbar in RelativeLayout so drawer layout is overlapping on it that's why you would not able to click on back arrow, i have fix your layout see below
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:navigationIcon="#drawable/ic_back_black"
app:popupTheme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:title="Settings" />
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/toolbar" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="#menu/options_menu" />
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
The simplest way would be to add parent activity in manifest file as developer docs suggest.
<activity
android:name=".ChildActivity"
android:parentActivityName=".ParentActivity" >
and java code you already have done it, setSupportActionbar and setHomeAsUpEnabled.
Edited :
its necessary to add up action for icon to be visible, as mentioned in
Android Developer Docs
So toolbar gives added flexibility to modify title-bar in Android.
As far as why getActionBar is not working and you are compelled to use getSupportActionBar is because you must be using SupportLibrary. SupportLibrary gives backward compatibility to earlier SDK versions.
If you want to modify your title-bar/header/action-bar extensively
then use toolbar otherwise use action-bar.
Add a navigation click listener to your toolbar , like below
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
If you are referencing some actions from the action bar, such as a Save action or a Share one, and you are overriding onOptionsItemSelected method, then you need to define the behavior when the back or home button is clicked:
#Override public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_save:
//save stuff
break;
//this is what you need to add to reference again back/home button
case android.R.id.home:
//do your stuff here, usually back to the home or close the current activity
getActivity().finish();
break;
default:
break;
}
return true;
I have a double-drawer layout set up and am trying to handle selecting items inside the drawers. The way I have it set up though, I can see that neither onNavigationItemSelected nor onOptionsItemSelected is getting called when I tap something on the menu (I put a log statement right inside the functions). I'm also not totally clear which of those functions should be called.
EDIT: It looks like onOptionsItemSelected() is being called after all, but whichever item I click on, I always get the same id. So maybe it's only allowing me to click some other layer?
There are a lot of other questions similar to this, but none of the answers have been helpful to me. I'd appreciate any insight you may have.
Here is the relevant code inside my onCreate() function in MainActivity.java:
// Adding Toolbar to Main screen
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView leftNavigationView = (NavigationView) findViewById(R.id.notifications_view);
leftNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem item) {
Log.i("left", "left"); // this is never called
// Handle left navigation view item clicks here
int id = item.getItemId();
switch(id) {
case R.id.emerg_con_menuitem:
break;
case R.id.ride_hist_menuitem:
Log.i("I'm hit", "I'm hit");
intent = new Intent(MainActivity.this, loc_report.class); // The action I want to happen when this menu item is tapped
MainActivity.this.startActivity(intent);
break;
case R.id.settings_menuitem:
break;
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
});
NavigationView rightNavigationView = (NavigationView) findViewById(R.id.nav_view);
rightNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem item) {
Log.i("right", "right"); // this is also never called
// Handle Right navigation view item clicks here.
int id = item.getItemId();
Log.i("I am firing", "I am firing");
switch(id) {
case R.id.emerg_con_menuitem:
break;
case R.id.ride_hist_menuitem:
Log.i("I'm hit navigation", "I'm hit navigation");
intent = new Intent(MainActivity.this, loc_report.class);
MainActivity.this.startActivity(intent);
break;
case R.id.settings_menuitem:
break;
}
drawer.closeDrawer(GravityCompat.END);
return true;
}
});
// Adding menu icon to Toolbar
ActionBar supportActionBar = getSupportActionBar();
if (supportActionBar != null) {
supportActionBar.setHomeAsUpIndicator(R.drawable.ic_notifications);
supportActionBar.setDisplayHomeAsUpEnabled(true);
supportActionBar.setDisplayShowTitleEnabled(false);
}
And the onOptionsItemSelected() that is being called, although not on the correct menu:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here.
Log.i("I'm hit options", "I'm hit options"); // also never called...what is going on??
int id = item.getItemId();
switch(id) {
case R.id.emerg_con_menuitem:
break;
case R.id.ride_hist_menuitem:
Log.i("I'm hit options", "I'm hit options");
Intent intent = new Intent(MainActivity.this, loc_report.class);
this.startActivity(intent);
break;
case R.id.settings_menuitem:
break;
case R.id.menu_navigation:
drawer.openDrawer(GravityCompat.END); /*Opens the Right Drawer*/
return true;
}
return super.onOptionsItemSelected(item);
}
Here is the main view activity_mail.xml:
<android.support.v4.widget.DrawerLayout
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"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="#drawable/main_background"
style="#style/Theme.AppCompat.DayNight">
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/Protectors"
app:elevation="0dp">
<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"
app:popupTheme="#style/Protectors"
android:textAlignment="center">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:fitsSystemWindows="true"
app:headerLayout="#layout/navheader"
app:menu="#menu/menu_navigation" />
<android.support.design.widget.NavigationView
android:id="#+id/notifications_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/navheader"
app:menu="#menu/notifications" />
...
The main menu with the clickable icon to open the drawer:
<?xml version="1.0" encoding="utf-8"?>
<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=".MainActivity">
<group android:checkableBehavior="single">
<item // this is the item that's being called on a click
android:id="#+id/menu_navigation"
android:icon="#drawable/ic_menu"
android:title="#string/action_notifications"
android:orderInCategory="100"
app:showAsAction="always" />
</group>
</menu>
and the stuff inside the drawer (the right-hand one):
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/emerg_con_menuitem"
android:title="Emergency Contacts"
/>
<item
android:id="#+id/ride_hist_menuitem"
android:title="Ride History" />
<item
android:id="#+id/settings_menuitem"
android:title="Settings" />
</menu>
Ok, I think I figured this out. I'm still having trouble with the right-drawer links, but I got the left-drawer links to work. It was a layering problem--so I was clicking on the main_menu item (which contains the clickable icon that makes the drawer open) instead of the menu items underneath. To fix this, I added this line of code to fix the order:
NavigationView leftNavigationView = (NavigationView) findViewById(R.id.nav_view);
leftNavigationView.bringToFront(); // <- added this line
And then the OnNavigationItemSelectedListener actually fires as expected.
I'm planning to implement a navigation bar to let users navigate to different activites.
But here's the problem,
I've found plenty articles about creating a navigation drawer but it seems doesn't work for me , because my UI doesn't have any titlebar.
And what i actually want is to call up the navigation drawer whenever users press on a button near to the navigation drawer.
Is there any possible way to do this ?
It is very simple.
Here is your main activity's layout, activity_main.xml:
<android.support.v4.widget.DrawerLayout
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/drawer_layout"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="match_parent">
<FrameLayout
android:animateLayoutChanges="true"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MergeRootFrame" />
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/drawer_list_header"
app:menu="#menu/navigation"/>
</android.support.v4.widget.DrawerLayout>
And here's your MainActivity:
public class MainActivity extends AppCompatActivity {
NavigationView navigationView;
DrawerLayout drawerLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.navi_1:
// on 1st item in the menu, do something
break;
case R.id.navi_2:
// on 2nd item in the menu, do something
break;
}
drawerLayout.closeDrawers();
return false;
}
});
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
}
// [...]
private void openDrawer() {
if (!drawerLayout.isDrawerOpen(navigationView)) {
drawerLayout.openDrawer(navigationView);
}
}
private void closeDrawer() {
if (drawerLayout.isDrawerOpen(navigationView)) {
drawerLayout.closeDrawers();
}
}
}
Now you can open the drawer with openDrawer() and close it with closeDrawer().
A sample navigation.xml file which is located under the menu dir in the res (resources) folder:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/navi_1"
android:checked="true"
android:icon="#drawable/ic_android"
android:title="First item"/>
<item
android:id="#+id/navi_2"
android:icon="#drawable/ic_android"
android:title="Second item"/>
</group>
</menu>
Sample drawer_list_header.xml file, located under the layout dir in the res folder:
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:paddingBottom="8dp"
android:src="#drawable/list_header_final">
</ImageView>
Here are some notes:
You have to declare a menu file for the drawer, see app:menu="#menu/navigation" in the layout file.
You might want to declare a header layout, which is displayed over the menu elements in the drawer, see app:headerLayout="#layout/drawer_list_header".
The drawer can be opened by a fling-like action from the edge of the screen. To prevent the users from doing that, you might want to lock/unlock your drawer on action using drawerLayout.setDrawerLockMode(...);, see the documentation for details.
Also note that in order to use NavigationView, you'll need the latest design support lib by adding the dependency to your module's gradle file: compile 'com.android.support:design:22.2.0'.
See more about it here.
Yes you can implement DrawerLayout with out ActionBar. You can manually open and close the DrawerLayout like
drawerLayout.openDrawer(Gravity.LEFT);
drawerLayout.closeDrawer(Gravity.LEFT);
First of all I know this question appeared here before but after trying a lot I still didn't succeed.
I working on the example from
Android Developers site.
I'm trying to set the menu to be opened from right to left instead of how its implementing in the example (from left to right). In addition I want to move the open menu button to the right side of the action bar. I also red some answers here, for example in this answer.
I try to change the gravity of the views and the layouts but I get the error:
no drawer view found with absolute gravity LEFT
Can you please help me to figure out what is the problem in my code and what should I change in order to set the menu to be opened from the right, and to move the action bar button to the right side?
the xml code is here:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_gravity="right"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/content_frame"
android:layoutDirection="rtl"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<ListView android:id="#+id/left_drawer"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="10dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
In your main layout set your ListView gravity to right:
android:layout_gravity="right"
Also in your code :
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, R.string.drawer_open,
R.string.drawer_close) {
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item != null && item.getItemId() == android.R.id.home) {
if (mDrawerLayout.isDrawerOpen(Gravity.RIGHT)) {
mDrawerLayout.closeDrawer(Gravity.RIGHT);
}
else {
mDrawerLayout.openDrawer(Gravity.RIGHT);
}
}
return false;
}
};
hope it works :)
Add this code to manifest:
<application android:supportsRtl="true">
and then write this code on Oncreate:
getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
It works for me. ;)
SOLUTION
your_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
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"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="end">
<include layout="#layout/app_bar_root"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:fitsSystemWindows="true"
app:itemTextColor="#color/black"
app:menu="#menu/activity_root_drawer" />
</android.support.v4.widget.DrawerLayout>
YourActivity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
//...
toolbar = (Toolbar) findViewById(R.id.toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (drawer.isDrawerOpen(Gravity.RIGHT)) {
drawer.closeDrawer(Gravity.RIGHT);
} else {
drawer.openDrawer(Gravity.RIGHT);
}
}
});
//...
}
This answer is useful to set the navigation be open from right to left, but it has no solution to set its icon to be right side. This code can fix it. If you give it the drawer as its first param and ViewCompat.LAYOUT_DIRECTION_RTL as its second param, the entier layout will be set to RTL. It is a quick and simple solution, but I don't think it can be a correct solution for who that want to only set the menu to be opened from right to left and set its icon to be on right side. (Although, it's depended to your purpose.) However, I suggest giving the toolbar instead of the drawer. In this way just the toolbar has become RTL. So I think the combination of these 2 answers can exactly do what you want.
According to these descriptions, your code should be like this:
(Add these lines to onCreate method)
final DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); // Set it final to fix the error that will be mention below.
ViewCompat.setLayoutDirection(toolbar, ViewCompat.LAYOUT_DIRECTION_RTL);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (drawer.isDrawerOpen(Gravity.RIGHT))
drawer.closeDrawer(Gravity.RIGHT);
else
drawer.openDrawer(Gravity.RIGHT);
}
});
Notice that you should make drawer final, otherwise you will get this error:
Variable 'drawer' is accessed from within inner class, needs to be
declared final
And don't forget to use end instead of start in onNavigationItemSelected method:
drawer.closeDrawer(GravityCompat.END);
and in your activity_main.xml
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
tools:openDrawer="end">
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_gravity="end"/>
</android.support.v4.widget.DrawerLayout>
Here is the documentation on the drawer and it appears that you can configure it to pull out from the left or right.
Drawer positioning and layout is controlled using the android:layout_gravity attribute on child views corresponding to which side of the view you want the drawer to emerge from: left or right. (Or start/end on platform versions that support layout direction.)
http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html
Take a look at this: slide ExpandableListView at DrawerLayout form right to left
I assume you have the ActionBarDrawerToggle implemented, the trick is to override the onOptionsItemSelected(MenuItem item) method inside the ActionBarDrawerToggle object with this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item != null && item.getItemId() == android.R.id.home) {
if (mDrawer.isDrawerOpen(Gravity.RIGHT)) {
mDrawer.closeDrawer(Gravity.RIGHT);
} else {
mDrawer.openDrawer(Gravity.RIGHT);
}
return true;
}
return false;
}
make sure and call this from onOptionsItemSelected(MenuItem item) in the Activity:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
This will allow you to use the the home button functionality. To move the button to the right side of the action bar you will have to implement a custom action item, and maybe some other stuff to get it to work like you want.
the main issue with the following error:
no drawer view found with absolute gravity LEFT
is that, you defined the
android:layout_gravity="right"
for list-view in right, but try to open the drawer from left, by calling this function:
mDrawerToggle.syncState();
and clicking on hamburger icon!
just comment the above function and try to handle open/close of menu like #Rudi said!
I have solved this problem by changing the gravity of the navigationview
android:layout_gravity
to end instead of start
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header"
app:menu="#menu/activity_drawer" />
It worked for me.
You should firstly put this code in your AppManifest.xml in the application tag:
android:supportsRtl="true"
then in your activity_main.xml file, put this piece of code:
android:layout_direction="rtl"
I did following modification to the Navigation Drawer Activity example in Android Studio. With support libraries 25.3.1.
MainActivity.java:
private DrawerLayout mDrawerLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(GravityCompat.END)) {
mDrawerLayout.closeDrawer(GravityCompat.END);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
switch (itemId) {
case android.R.id.home:
finish();
return true;
case R.id.action_right_drawer:
if (mDrawerLayout.isDrawerOpen(GravityCompat.END)) {
mDrawerLayout.closeDrawer(GravityCompat.END);
} else {
mDrawerLayout.openDrawer(GravityCompat.END);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
mDrawerLayout.closeDrawer(GravityCompat.END);
return true;
}
main.xml (download ic_menu_white_24px from https://material.io/icons/):
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="#+id/action_right_drawer"
android:title="Drawer menu"
android:icon="#drawable/ic_menu_white_24px"
android:orderInCategory="100"
app:showAsAction="always" />
</menu>
In activity_main.xml change
android:layout_gravity="start"
to
android:layout_gravity="end"
Making it open from rtl isn't good for user experience, to make it responsive to the user locale I just added the following line to my DrawerLayout parameters:
android:layoutDirection="locale"
Added it to my AppBarLayout to make the hamburger layout match the drawer opening direction too.
DrawerLayout Properties
android:layout_gravity="right|end" and tools:openDrawer="end"
NavigationView Property
android:layout_gravity="end"
XML Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:layout_gravity="right|end"
tools:openDrawer="end">
<include layout="#layout/content_main" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
Java Code
// Appropriate Click Event or Menu Item Click Event
if (drawerLayout.isDrawerOpen(GravityCompat.END))
{
drawerLayout.closeDrawer(GravityCompat.END);
}
else
{
drawerLayout.openDrawer(GravityCompat.END);
}
//With Toolbar
toolbar = (Toolbar) findViewById(R.id.toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Gravity.END or Gravity.RIGHT
if (drawer.isDrawerOpen(Gravity.END)) {
drawer.closeDrawer(Gravity.END);
} else {
drawer.openDrawer(Gravity.END);
}
}
});
//...
}
In your layout file inside NavigationView set this attribute android:layout_gravity="end" and set tools:openDrawer="end" in the DrawerLayout
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".tasks.TasksActivity"
android:id="#+id/drawer_layout"
tools:openDrawer="end">
<!-- Navigation Drawer -->
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="end"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header"
app:menu="#menu/drawer_actions" />
</androidx.drawerlayout.widget.DrawerLayout>
Output
I know this is an old question, but I've been struggling with this problem for a few days now and finally achived the solution.
If you want to use the default new project "Navigation Drawer Activity" to work with a drawer from right to left:
Create a custom DrawerLayout class:
public class CustomDrawerLayout extends DrawerLayout {
public CustomDrawerLayout(#NonNull Context context) {
super(context);
}
public CustomDrawerLayout(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public CustomDrawerLayout(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void open() {
openDrawer(GravityCompat.END);
}
#Override
public void close() {
closeDrawer(GravityCompat.END);
}
#Override
public boolean isOpen() {
return isDrawerOpen(GravityCompat.END);
}
}
On activity_main.xml:
set DrawerLayout tools:openDrawer="end"
set NavigationView android:layout_gravity="end"
change tag view from androidx.drawerlayout.widget.DrawerLayout to your CustomDrawerLayout com.example.CustomDrawerLayout
If you create new menu options, it is important that the id of the item in menu/activity_main_drawer.xml is the same as the id of the fragment in navigation/mobile_navigation.xml.
Summarising multiple answers into one which worked for me.
Following were my requirements
1. Align navigation drawer hamburger icon to write
2. Start the navigation drawer from right to left
3. Achieve the above two points without changing the direction to rtl of the whole layout
To start the Navigation drawer from right to left
Set DrawerLayout tools:openDrawer="end"
Set NavigationView android:layout_gravity="end"
mDrawerToggle.setToolbarNavigationClickListener {
if (binding.drawerLayout.isDrawerOpen(GravityCompat.END)) {
binding.drawerLayout.closeDrawer(GravityCompat.END)
} else {
binding.drawerLayout.openDrawer(GravityCompat.END)
}
}
To set the Hamburger menu to the right
Set AppBarLayout android:layoutDirection="rtl"