Як встановити, щоб навігаційну шухляду відкривалося справа наліво


85

Перш за все, я знаю, що це питання з’явилося тут раніше, але після багатьох спроб мені все одно не вдалося. Я працюю на прикладі з веб-сайту розробників 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, чому ти не використовуєш спеціальну панель дій?
Руді

@Rudi: Ви маєте на увазі setCustomViewметод? Якщо так, чи не могли б ви вставити кілька посилань, де показано, як це зробити?
Аліреза Фарахані

@alireza Я мав на увазі, замість того, щоб використовувати панель дій у верхній частині вашого перегляду, зробіть власну панель дій у вашому основному xml та встановіть її так, як хочете ви.
Руді

@Rudi: Але як же я можу досягти такої самої поведінки, як навігація вгору та анімація відкриття та закриття шухляди? Чи потрібно їх реалізовувати з нуля?
Аліреза Фарахані

62

Додайте цей код до маніфесту:

<application android:supportsRtl="true">

а потім напишіть цей код на Oncreate:

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

Це працює для мене. ;)


1
це правильна відповідь, просто встановіть для початку важкість перегляду списку, а потім скористайтеся цим кодом, все повинно бути добре
Mahdi Giveie

9
Працює, однак, setLayoutDirection (View.LAYOUT_DIRECTION_RTL) призначений для API вище 17, тому ви не можете використовувати це для api нижчої
Milad,

6
Чи не переверне це весь макет діяльності, навіть toStartOf / toEndOf тощо ...?
TWiStErRob

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
Чудово працює. Але значок панелі інструментів все ще відображається зліва. Як також перевести піктограму перемикача вправо?
Даруш

я дав android: layout_gravity = "end" як для Drawerlayout, так і для NavigationView, він працює нормально.
varotariya vajsi

toolbar.setNavigationOnClickListenerпотрібно min min Api Level 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).(Google)
Володимир Кулик

2
Додайте android: layoutDirection = "rtl" у свій AppBarLayout XML, щоб встановити кнопку перемикання вправо
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);
        }
    });

Зверніть увагу, що ви повинні зробити шухляду остаточною, інакше ви отримаєте таку помилку:

До змінної "шухляда" можна отримати доступ з внутрішнього класу, її потрібно оголосити остаточною

І не забудьте використовувати endзамість startin onNavigationItemSelectedmethod:

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
сторону

1
я все-таки отримав помилку: жодного виду шухляди не знайдено з абсолютною вагою вліво. Я додав до маніфесту android: supportsRtl = "true", а в xml під ящиком Layout я додав android: layoutDirection = "rtl", а потім меню відкриється праворуч, але тепер воно не закривається, коли я натискаю кнопка меню (на панелі дій), коли я натискаю будь-який елемент у списку, або зовні зі списку, який він закриває, але ні, коли я натискаю кнопку меню на панелі дій, будь-які ідеї, чому?
galvan

Я не зовсім впевнений, але ... оскільки напрямок і положення шухляди тепер змінено, у вашій діяльності, як на прикладі Android, ви повинні мати метод перемикача перемикача / прослуховувач кнопок, перевірте, чи потрібно це робити модифікований таким чином, щоб він знав, що закрити, перемістивши його 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)в Діяльність:

@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

Я вирішив цю проблему, змінивши важкість навігаційного перегляду

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, щоб макет гамбургера теж відповідав напрямку відкривання шухляди.


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);
            }
        }
    });
//...
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.