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

Posted

技术标签:

【中文标题】如何设置导航抽屉从右到左打开【英文标题】:How to set Navigation Drawer to be opened from right to left 【发布时间】:2013-09-04 00:45:21 【问题描述】:

首先我知道这个问题之前出现过,但是尝试了很多之后我仍然没有成功。 我研究的例子来自 android Developers site.

我正在尝试将菜单设置为从右到左打开,而不是在示例中的实现方式(从左到右)。另外我想将打开菜单按钮移动到操作栏的右侧。我这里也把一些答案红了,比如in this answer。

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

没有找到绝对重力左侧的抽屉视图

您能否帮我弄清楚我的代码中存在什么问题以及我应该更改什么才能将菜单设置为从右侧打开并将操作栏按钮移动到右侧?

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_
    android:layout_ >

    <FrameLayout
        android:id="@+id/content_frame"
        android:layoutDirection="rtl"
        android:layout_
        android:layout_
        />

    <ListView android:id="@+id/left_drawer"
        android:layout_
        android:layout_
        android:layout_gravity="right"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="10dp"
        android:background="#111"/>

</android.support.v4.widget.DrawerLayout>

【问题讨论】:

slide ExpandableListView at DrawerLayout form right to left的可能重复 看看github.com/Ali-Rezaei/SlidingDrawer,它可以通过几行代码从任何一侧滑动。 请看答案***.com/a/44076363/5332645 如果您正在使用导航组件,请查看this answer。 【参考方案1】:

在您的主布局中,将您的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;
    
;

希望它有效:)

【讨论】:

@Rudi:你知道第二部分的答案吗?我的意思是如何从右到左制作动作栏。 (抽屉和向上导航图标方向也会改变) @alireza 为什么不使用自定义操作栏? @Rudi:你的意思是setCustomView方法?如果是,您介意粘贴一些链接来说明如何做到这一点吗? @alireza 我的意思是,不要在视图顶部使用操作栏,而是在主 xml 中创建自定义操作栏并根据需要进行设置。 @Rudi:但是,我怎样才能实现与向上导航和抽屉打开和关闭动画相同的行为呢?我必须从头开始实施它们吗?【参考方案2】:

将此代码添加到清单中:

<application android:supportsRtl="true">

然后在 Oncreate 上写下这段代码:

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

它对我有用。 ;)

【讨论】:

这是正确答案,只需设置您的列表视图的重力启动,然后使用此代码,一切都应该没问题 它正在工作,但是,setLayoutDirection(View.LAYOUT_DIRECTION_RTL) 是针对 17 以上的 API,所以你不能将它用于 api lower 这不会翻转整个activity的布局,甚至是toStartOf/toEndOf等...? 这是错误的答案。它从右到左翻转整个活动布局。 认为这是一个快速的解决方案,但不是一个正确的解决方案。【参考方案3】:

解决方案


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_
    android:layout_
    android:fitsSystemWindows="true"
    tools:openDrawer="end">

    <include layout="@layout/app_bar_root"
        android:layout_
        android:layout_ />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_
        android:layout_
        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);
            
        
    );
//...

【讨论】:

效果很好。但是工具栏图标仍然出现在左侧。如何将切换按钮图标也向右移动? 我也为 Drawerlayout 和 NavigationView 提供了 android:layout_gravity="end",它工作正常。 toolbar.setNavigationOnClickListener 要求最低 Api 级别 21 :( @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) 在您的 AppBarLayout XML 中添加 android:layoutDirection="rtl" 以将切换按钮设置为右侧【参考方案4】:

This answer 对设置导航从右到左打开很有用,但没有解决方法将其图标设置为右侧。 This code 可以修复它。如果你给它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);
        
    );

注意你要把drawer设为final,否则你会得到这个错误:

从内部类中访问变量“抽屉”,需要 最终宣布

并且不要忘记在onNavigationItemSelected 方法中使用end 而不是start

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>

【讨论】:

【参考方案5】:

这是抽屉上的文档,您可以将其配置为从左侧或右侧拉出。

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

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

【讨论】:

我之前看到过这个答案,在我的问题中也提到过。 好的。尝试在重力中使用end 而不是right。编辑:从android.support...DrawerLayout 中删除android:layout_gravity="right" 并将android:layout_gravity="right" 更改为android:layout_gravity="end"ListView 我仍然收到错误:在绝对重力左侧找不到抽屉视图。我添加到清单android:supportsRtl =“true”,并在drawerLayout下的xml中添加了android:layoutDirection =“rtl”,然后菜单在右侧打开,但现在当我点击时它没有关闭菜单按钮(在操作栏中)当我点击列表中的任何项目时,或者在列表之外它关闭但当我点击操作栏中的菜单按钮时没有,任何想法为什么? 我不完全确定,但是......随着抽屉的方向和位置现在改变了,在你的活动中,根据 Android 示例,你应该有切换开关方法/按钮侦听器,检查是否需要对其进行修改,以便它知道通过将其从右到左移动来关闭。它可能认为菜单已经在左侧(即隐藏)所以它不会关闭(如果有意义的话)...... 伙计们,我也在做同样的事情,但如果使用 laoutDirection="rtl" 那么我必须将 minSdk 更改为 17,但我的应用程序需要支持 API 级别 10。你们能帮帮我吗我的应用可以支持 API 10。【参考方案6】:

看看这个:slide ExpandableListView at DrawerLayout form right to left

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

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

确保在 Activity 中从 onOptionsItemSelected(MenuItem item) 调用它:

@Override
public boolean onOptionsItemSelected(MenuItem item) 

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


return super.onOptionsItemSelected(item);

这将允许您使用主页按钮功能。要将按钮移动到操作栏的右侧,您必须实现一个自定义操作项,可能还需要一些其他的东西才能让它像您想要的那样工作。

【讨论】:

【参考方案7】:

主要问题有以下错误:

找不到绝对重力左侧的抽屉视图

是,你定义了

android:layout_gravity="right"

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

mDrawerToggle.syncState();

然后点击汉堡图标!

只需评论上面的函数并尝试像@Rudi所说的那样处理菜单的打开/关闭!

【讨论】:

【参考方案8】:

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

android:layout_gravity

end 而不是 start

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_
        android:layout_
        android:layout_gravity="end"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/activity_drawer" />

它对我有用。

【讨论】:

【参考方案9】:

你应该先把这段代码放在你的 AppManifest.xml 中的应用标签中:

android:supportsRtl="true"

然后在你的 activity_main.xml 文件中,放入这段代码:

android:layout_direction="rtl"

【讨论】:

这是有史以来最好的解决方案,谢谢您节省我的时间【参考方案10】:

我对 Android Studio 中的 Navigation Drawer Activity 示例进行了以下修改。支持库 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"

【讨论】:

【参考方案11】:

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

android:layoutDirection="locale"

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

【讨论】:

【参考方案12】:

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_
    android:layout_
    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_
        android:layout_
        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);
            
        
    );
//...

【讨论】:

【参考方案13】:

在 NavigationView 内的布局文件中设置此属性 android:layout_gravity="end" 并设置 tools:openDrawer="end" 在 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_
    android:layout_
    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_
        android:layout_
        android:layout_gravity="end"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/drawer_actions" />

</androidx.drawerlayout.widget.DrawerLayout>

输出

【讨论】:

以上是关于如何设置导航抽屉从右到左打开的主要内容,如果未能解决你的问题,请参考以下文章

react native - 改变导航方向(即从右到左)

从右到左滑动抽屉菜单

在Xamarin android中从右向左滑动抽屉

如何从右到左设计android.support.design.widget.NavigationView?

Xcode Segue View Controller 从右到左没有 UINavigation

反转 SWIFT 中导航控制器的默认转换 [重复]