如何设置导航抽屉从右向左打开

首先,我知道这个问题以前在这里出现过,但在尝试了很多之后,我仍然没有成功。 我正在研究 Android 开发者网站

我试图设置菜单从右到左打开,而不是如何在示例中实现(从左到右)。另外,我想把打开的菜单按钮移动到操作栏的右侧。我还在这里用红色标出了一些答案,例如 在这个答案中

我试图改变视图和布局的严重性,但我得到了错误:

没有发现绝对重力向左的抽屉视图

你能帮我找出我的代码有什么问题吗? 为了设置菜单从右边打开,并将操作栏按钮移动到右边,我应该做些什么修改?

Xml 代码在这里:

<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>
135434 次浏览

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.

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. ;)



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);
}
}
});
//...
}

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"

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.

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.

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>

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

enter image description here

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"

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:

  1. 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);
}


}
  1. 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.