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


83

首先,我知道这个问题以前曾出现在这里,但经过很多尝试,我仍然没有成功。我在Android Developers网站上处理示例 。

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

我尝试更改视图和布局的重力,但出现错误:

绝对重力未找到抽屉视图

您能帮我找出代码中的问题是什么,我应该更改什么才能将菜单设置为从右侧打开,并将操作栏按钮移至右侧?

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>


看一下github.com/Ali-Rezaei/SlidingDrawer,它使得从任何一侧滑动几行代码成为可能。
阿里

Answers:


154

在主布局中,将ListView重力设置为正确:

android:layout_gravity="right" 

同样在您的代码中:

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;
    }
};

希望它能工作:)


2
@Rudi:你知道第二部分的答案吗?我的意思是如何使操作栏从右到左。(抽屉和向上导航图标的方向也会更改)
Alireza Farahani 2014年

@alireza为什么不使用自定义操作栏?
鲁迪2014年

@Rudi:你是说setCustomView方法吗?如果是,您介意粘贴一些链接来显示如何执行此操作吗?
Alireza Farahani 2014年

@alireza我的意思是,不要在视图顶部使用操作栏,而是在主xml中创建自定义操作栏,然后根据需要进行设置。
鲁迪2014年

@Rudi:但是,如何实现相同的行为,例如向上导航和抽屉打开和关闭动画?我是否必须从头开始实施它们?
Alireza Farahani 2014年

61

添加以下代码以实现清单:

<application android:supportsRtl="true">

然后在Oncreate上编写以下代码:

getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);

这个对我有用。;)


1
这是正确的答案,只需将listview的引力设置为start,然后使用此代码,一切就可以了
Mahdi Giveie 2014年

9
它正在运行,但是setLayoutDirection(View.LAYOUT_DIRECTION_RTL)适用于17以上的API,因此您不能将其用于较低的api
Milad 2015年

6
这不会翻转活动的整个布局,甚至toStartOf / toEndOf等...吗?
TWiStErRob 2015年

13
这是错误的答案。它将整个活动布局从右向左翻转。
塔伦

1
认为这是一种快速解决方案,但不是正确的解决方案。
sidhanshu

37



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

2
效果很好。但是工具栏图标仍显示在左侧。如何将切换按钮图标也向右移?
达拉什

我也为Drawerlayout和NavigationView提供了android:layout_gravity =“ end”,它的工作正常。
varotariya vajsi

toolbar.setNavigationOnClickListener需要最低Api级别21 :(
SepJaPro2.4 '18

@ SepJaPro2.4是,但是From August 2018, new apps must target at least Android 8.0 (API level 26). From November 2018, app updates must target Android 8.0 (API level 26).(Google)
Volodymyr Kulyk,

2
在您的AppBarLayout XML中添加android:layoutDirection =“ rtl”以将切换按钮设置为右侧
Terranology

4

此答案对于将导航设置为从右到左打开很有用,但是无法将其图标设置为右侧。此代码可以修复它。如果将其drawer作为第一个参数,ViewCompat.LAYOUT_DIRECTION_RTL并将其作为第二个参数,则整个布局将设置为RTL。这是一个快速简单的解决方案,但是对于那些只希望将菜单设置为从右向左打开并将其图标设置在右侧的人,我认为这不是一个正确的解决方案。(尽管这取决于您的目的。)但是,我建议使用toolbar而不是drawer。这样,只有工具栏已成为RTL。因此,我认为这两个答案的组合可以完全满足您的需求。

根据这些描述,您的代码应如下所示:

(将这些行添加到onCreate方法中)

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

请注意,您应该将抽屉做为最终抽屉,否则会出现此错误:

从内部类中访问变量“抽屉”,需要将其声明为final

而且不要忘了使用end,而不是startonNavigationItemSelected方法:

drawer.closeDrawer(GravityCompat.END);

并在您的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>

3

这是抽屉上的文档,似乎您可以对其进行配置以从左侧或右侧拉出。

抽屉的位置和布局是通过子视图上的android:layout_gravity属性控制的,子视图对应于您希望抽屉从哪个视图出现的一侧:左侧还是右侧。(或在支持布局方向的平台版本上开始/结束。)

http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html


我之前看到过这个答案,并且在我的问题中也提到了它。
galvan

好的。尝试使用end代替right重力。编辑:android:layout_gravity="right"从中删除android.support...DrawerLayout并更改android:layout_gravity="right"android:layout_gravity="end"内部ListView
KickAss

1
我仍然收到错误:绝对重力向左找不到抽屉视图。我将清单android:supportsRtl =“ true”添加到清单中,并在DrawerLayout下的xml中添加了android:layoutDirection =“ rtl”,然后菜单在右侧打开,但是现在当我按一下时,它不会关闭菜单按钮(在操作栏中),当我单击列表中的任何项目时,或者从列表外部单击时,它都会关闭,但是当我单击操作栏中的菜单按钮时却没有,为什么有什么主意?
galvan

我不完全确定,但是...由于Drawer的方向和位置现在已更改,因此在您的Activity中,按照Android示例,您应该具有Toggle切换方法/按钮侦听器,请检查是否需要修改,以便它知道通过将其向右移动来关闭。可能是因为认为菜单上的保持菜单已经位于左侧(即隐藏),所以它不会关闭(如果有意义)...
KickAss

伙计们,我也在做同样的事情,但是如果使用laoutDirection =“ rtl”,那么我必须将minSdk更改为17,但是我的应用程序需要支持API级别10。你们可以帮我吗,以便我的应用程序可以支持API 10。
Aditya

3

看一下这个:从右向左滑动DrawerLayout窗体的ExpandableListView

我假设您已经实现了ActionBarDrawerToggle,诀窍是使用以下onOptionsItemSelected(MenuItem item)方法覆盖ActionBarDrawerToggle对象内的方法:

    @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;
    }

确保从onOptionsItemSelected(MenuItem item)活动中调用此命令:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

if(mDrawerToggle.onOptionsItemSelected(item)) {
    return true;
}

return super.onOptionsItemSelected(item);
}

这将允许您使用主页按钮功能。要将按钮移到操作栏的右侧,您将必须实现一个自定义操作项,可能还需要实现一些其他功能才能使其按您的意愿工作。


3

出现以下错误的主要问题:

绝对重力未找到抽屉视图

是的,您定义了

android:layout_gravity="right"

用于右侧的列表视图,但尝试通过调用此函数从左侧打开抽屉:

mDrawerToggle.syncState();

然后点击汉堡图标!

只需评论上面的功能并尝试处理菜单的打开/关闭,如@Rudi所说!


3

我已经通过更改NavigationView的重力解决了这个问题

android:layout_gravity

结束,而不是开始

<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" />

它为我工作。



2

我对Android Studio中的“导航抽屉活动”示例进行了以下修改。带有支持库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(从https://material.io/icons/下载ic_menu_white_24px ):

<?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>

在activity_main.xml中进行更改

android:layout_gravity="start"

android:layout_gravity="end"

2

从rtl中打开它不利于用户体验,为了使其响应用户区域设置,我在DrawerLayout参数中添加了以下行:

android:layoutDirection="locale"

将其添加到我的AppBarLayout中,以使汉堡包布局也与抽屉打开方向匹配。


1

DrawerLayout属性 android:layout_gravity="right|end"tools:openDrawer="end" NavigationView属性 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);
            }
        }
    });
//...
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.