Как настроить открытие панели навигации справа налево

86

Прежде всего, я знаю, что этот вопрос появлялся здесь раньше, но после многих попыток мне все равно не удалось. Я работаю над примером с сайта разработчиков 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>
гальван
источник
Взгляните на github.com/Ali-Rezaei/SlidingDrawer, который позволяет скользить с любой стороны с помощью нескольких строк кода.
Али
См. Ответ stackoverflow.com/a/44076363/5332645
Аман Саксена,

Ответы:

155

В основном макете установите 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, почему вы не используете настраиваемую панель действий?
Руди
@ Руди: Вы имеете в виду setCustomViewметод? Если да, не могли бы вы вставить несколько ссылок, показывающих, как это сделать?
Алиреза Фарахани
@alireza Я имел в виду, вместо того, чтобы использовать панель действий в верхней части вашего представления, сделайте свою настраиваемую панель действий в своем основном xml и настройте ее по своему усмотрению.
Руди
@Rudi: Но тогда как я могу добиться такого же поведения, как навигация вверх и анимация открытия и закрытия ящика? Придется ли мне внедрять их с нуля?
Алиреза Фарахани
62

Добавьте этот код в манифест:

<application android:supportsRtl="true">

а затем напишите этот код в Oncreate:

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

Меня устраивает. ;)

Амир Бакс
источник
1
это правильный ответ, просто установите гравитацию вашего списка для начала, затем используйте этот код, все должно быть в порядке
Махди Гиви
9
Однако он работает, setLayoutDirection (View.LAYOUT_DIRECTION_RTL) предназначен для API выше 17, поэтому вы не можете использовать его для API ниже
Милад
6
Разве это не перевернет всю схему действия, даже toStartOf / toEndOf и т. Д.?
TWiStErRob
14
Это неправильный ответ. Он переворачивает всю схему действий справа налево.
Tarun
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
Работает отлично. Но значок на панели инструментов по-прежнему отображается слева. Как также переместить значок кнопки переключения вправо?
Darush 05
Я дал android: layout_gravity = "end" как для Drawerlayout, так и для NavigationView, он работает нормально.
varotariya vajsi 09
toolbar.setNavigationOnClickListenerтребуется минимальный уровень Api 21 :(
SepJaPro2.4
@ 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).(гугл)
Владимир Кулик
2
Добавьте android: layoutDirection = "rtl" в свой AppBarLayout XML, чтобы установить переключатель вправо
Terranology
4

Этот ответ полезен для открытия навигации справа налево, но у него нет решения, чтобы установить значок справа. Этот код может это исправить. Если вы укажете ему в drawerкачестве первого параметра и в ViewCompat.LAYOUT_DIRECTION_RTLкачестве второго параметра, для макета entier будет установлено значение 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' осуществляется из внутреннего класса, ее необходимо объявить окончательной

И не забудьте использовать endвместо метода startin onNavigationItemSelected:

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

Надрать задницу
источник
Я видел этот ответ раньше и также упомянул об этом в своем вопросе.
гальван
Хорошо. Попробуйте использовать endвместо rightсилы тяжести. РЕДАКТИРОВАТЬ: удалить android:layout_gravity="right"из android.support...DrawerLayoutи заменить android:layout_gravity="right"на android:layout_gravity="end"внутреннюю частьListView
KickAss
1
У меня все еще есть ошибка: не найдено ни одного вида ящика с абсолютной гравитацией СЛЕВА. Я добавил в манифест android: supportsRtl = "true", а в xml под drawerLayout я добавил android: layoutDirection = "rtl", а затем меню открывается справа, но теперь оно не закрывается, когда я нажимаю кнопку Кнопка меню (на панели действий), когда я нажимаю на любой элемент в списке или вне списка, он закрывается, но нет, когда я нажимаю кнопку меню на панели действий, есть идеи, почему?
гальван
Я не совсем уверен, но ... поскольку направление и положение ящика теперь изменены, в вашей деятельности, в соответствии с примером Android, у вас должен быть прослушиватель метода / кнопки Toggle switch, проверьте, нужно ли это изменен так, чтобы он знал, что нужно закрыть, перемещая его RightToLeft. Возможно, он думает, что удержание в меню уже слева (т.е. скрыто), поэтому оно не закроется (если в этом есть смысл) ...
KickAss
Ребята, я тоже делаю то же самое, но если я использую laoutDirection = "rtl", тогда мне нужно изменить minSdk на 17, но мое приложение должно поддерживать уровень API 10. Ребята, вы можете мне помочь, чтобы мое приложение могло поддерживать API 10.
Адитья
3

Взгляните на это: сдвиньте ExpandableListView в форму DrawerLayout справа налево

Я предполагаю, что у вас реализован 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)в Activity:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

return super.onOptionsItemSelected(item);
}

Это позволит вам использовать функциональность кнопки «Домой». Чтобы переместить кнопку в правую часть панели действий, вам нужно будет реализовать настраиваемый элемент действия и, возможно, некоторые другие вещи, чтобы заставить его работать так, как вы хотите.

d370urn3ur
источник
3

основная проблема со следующей ошибкой:

не найден вид ящика с абсолютной гравитацией СЛЕВА

это вы определили

android:layout_gravity="right"

для просмотра списка справа, но попробуйте открыть ящик слева, вызвав эту функцию:

mDrawerToggle.syncState();

и нажав на значок гамбургера!

просто прокомментируйте вышеуказанную функцию и попробуйте обработать открытие / закрытие меню, как сказал @Rudi!

par4301
источник
3

Я решил эту проблему, изменив степень тяжести навигации

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

Сначала вы должны поместить этот код в свой AppManifest.xml в теге приложения:

android:supportsRtl="true"

затем в файле activity_main.xml поместите этот фрагмент кода:

android:layout_direction="rtl"
Шабнам Эсмаили
источник
это лучшее решение, ты спасешь меня, спасибо
Ахмед Муса
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 (загрузите ic_menu_white_24px с 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>

В activity_main.xml измените

android:layout_gravity="start"

к

android:layout_gravity="end"
Матиас Джеппссон
источник
2

Открытие его из rtl не очень удобно для пользователя, чтобы он реагировал на локаль пользователя, я просто добавил следующую строку в свои параметры DrawerLayout:

android:layoutDirection="locale"

Добавил его в свой AppBarLayout, чтобы макет гамбургера соответствовал направлению открытия ящика.

arbel03
источник
1

Свойства DrawerLayoutandroid:layout_gravity="right|end" и свойство tools:openDrawer="end" NavigationViewandroid: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);
            }
        }
    });
//...
}
Ашвин соланки
источник