Jak ustawić szufladę nawigacji, aby otwierała się od prawej do lewej

85

Przede wszystkim wiem, że to pytanie pojawiło się tutaj wcześniej, ale po wielu próbach nadal mi się nie udało. Pracuję na przykładzie ze strony Android Developers .

Próbuję ustawić menu tak, aby było otwierane od prawej do lewej, zamiast tego, jak jest to implementowane w przykładzie (od lewej do prawej). Ponadto chcę przenieść przycisk otwierania menu na prawą stronę paska akcji. Podkreśliłem też tutaj niektóre odpowiedzi, na przykład w tej odpowiedzi .

Próbuję zmienić grawitację widoków i układy ale wyskakuje mi błąd:

nie znaleziono widoku szuflady z grawitacją absolutną LEWA

Czy możesz mi pomóc dowiedzieć się, na czym polega problem w moim kodzie i co powinienem zmienić, aby ustawić menu na otwieranie z prawej strony i przesunąć przycisk paska akcji na prawą stronę?

kod xml jest tutaj:

<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>
ocynk
źródło
Zajrzyj na stronę github.com/Ali-Rezaei/SlidingDrawer, która umożliwia przesuwanie z dowolnej strony kilkoma wierszami kodu.
Ali
Zobacz odpowiedź stackoverflow.com/a/44076363/5332645
Aman Saxena,

Odpowiedzi:

155

W głównym układzie ustaw ListViewgrawitację w prawo:

android:layout_gravity="right" 

Również w Twoim kodzie:

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

mam nadzieję, że zadziała :)

Rudi
źródło
2
@Rudi: Czy znasz odpowiedź z drugiej części? Mam na myśli, jak zrobić pasek akcji od prawej do lewej. (Szuflada i kierunek ikony nawigacji w górę również się zmieniają)
Alireza Farahani,
@alireza, dlaczego nie używasz niestandardowego paska akcji?
Rudi
@Rudi: Masz na myśli setCustomViewmetodę? Jeśli tak, czy mógłbyś wkleić kilka linków pokazujących, jak to zrobić?
Alireza Farahani
@alireza Chodziło mi o to, że zamiast używać paska akcji w górnej części widoku, utwórz niestandardowy pasek akcji w głównym pliku XML i skonfiguruj go tak, jak chcesz.
Rudi
@Rudi: Ale w takim razie, jak mogę osiągnąć to samo zachowanie, jak nawigacja w górę i animacja otwierania i zamykania szuflady? Czy muszę je wdrażać od podstaw?
Alireza Farahani,
62

Dodaj ten kod do manifestu:

<application android:supportsRtl="true">

a następnie napisz ten kod w Oncreate:

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

Mi to pasuje. ;)

Amir Bax
źródło
1
to jest poprawna odpowiedź, po prostu ustaw wagę widoku listy, aby rozpocząć, a następnie użyj tego kodu, wszystko powinno być w porządku
Mahdi Giveie
9
Działa jednak, setLayoutDirection (View.LAYOUT_DIRECTION_RTL) jest dla API powyżej 17, więc nie możesz tego użyć dla niższego api
Milad
6
Czy nie spowoduje to odwrócenia całego układu działania, nawet toStartOf / toEndOf itp ...?
TWiStErRob
13
To jest zła odpowiedź. Odwraca cały układ czynności od prawej do lewej.
Tarun
1
Myślałem, że to szybkie rozwiązanie, ale nie jest to właściwe.
sidhanshu
37

ROZWIĄZANIE


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);
            }
        }
    });
//...
}
Volodymyr Kulyk
źródło
2
Działa świetnie. Ale ikona paska narzędzi nadal pojawia się po lewej stronie. Jak również przenieść ikonę przycisku przełączania w prawo?
Darush
Dałem android: layout_gravity = "end" zarówno dla Drawerlayout, jak i NavigationView, działa dobrze.
varotariya vajsi
toolbar.setNavigationOnClickListenerwymaga min. poziomu Api 21 :(
SepJaPro2.4
@ SepJaPro2.4 tak, ale 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
Dodaj android: layoutDirection = "rtl" do pliku XML AppBarLayout, aby ustawić przycisk przełączania po prawej stronie
Terranology
4

Ta odpowiedź jest przydatna, aby ustawić nawigację od prawej do lewej, ale nie ma rozwiązania, aby ustawić jej ikonę na prawą stronę. Ten kod może to naprawić. Jeśli podasz mu drawerjako pierwszy parametr i ViewCompat.LAYOUT_DIRECTION_RTLjako drugi parametr, układ wejściowy zostanie ustawiony na RTL. Jest to szybkie i proste rozwiązanie, ale nie sądzę, aby było to właściwe rozwiązanie dla tych, którzy chcą tylko ustawić otwieranie menu od prawej do lewej i ustawić jego ikonę po prawej stronie. (Chociaż jest to zależne od twojego celu.) Jednak sugeruję podanie toolbarzamiast drawer. W ten sposób tylko pasek narzędzi stał się RTL. Więc myślę, że połączenie tych 2 odpowiedzi może zrobić dokładnie to, co chcesz.

Zgodnie z tymi opisami Twój kod powinien wyglądać tak:

(Dodaj te linie do metody 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);
        }
    });

Zauważ, że powinieneś ustawić szufladę jako ostateczną, w przeciwnym razie pojawi się ten błąd:

Dostęp do zmiennej „szuflada” uzyskuje się z poziomu klasy wewnętrznej i należy ją uznać za ostateczną

I nie zapomnij użyć endzamiast startw onNavigationItemSelectedmetodzie:

drawer.closeDrawer(GravityCompat.END);

oraz w Twoim pliku 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>
Reyhaneh Sharifzadeh
źródło
3

Oto dokumentacja szuflady i wygląda na to, że można ją skonfigurować tak, aby wysuwała się z lewej lub prawej strony.

Pozycjonowanie i układ szuflady jest kontrolowane za pomocą atrybutu android: layout_gravity w widokach potomnych, odpowiadających stronie widoku, z której szuflada ma się wyłonić: z lewej lub z prawej strony. (Lub rozpocznij / zakończ w wersjach platformy, które obsługują kierunek układu).

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

Skopać tyłek
źródło
Widziałem tę odpowiedź już wcześniej, a także wspomniałem o niej w swoim pytaniu.
galwan
W porządku. Spróbuj użyć endzamiast rightgrawitacji. EDYCJA: Usuń android:layout_gravity="right"z android.support...DrawerLayouti zmień android:layout_gravity="right"na android:layout_gravity="end"wnętrzeListView
KickAss
1
Nadal pojawia się błąd: nie znaleziono widoku szuflady z grawitacją absolutną LEWA. Dodałem do manifestu android: supportRtl = "true", aw xml pod drawerLayout dodałem android: layoutDirection = "rtl", a potem menu otwiera się po prawej stronie, ale teraz nie zamyka się po kliknięciu przycisk menu (na pasku akcji), kiedy klikam dowolną pozycję na liście lub poza listą, zamyka się, ale nie, kiedy klikam przycisk menu na pasku akcji, jakieś pomysły dlaczego?
galwan
Nie jestem do końca pewien, ale ... ponieważ kierunek i pozycja szuflady jest teraz zmieniona, w Twojej aktywności, jak na przykładzie Androida, powinieneś mieć odbiornik przełączania metody / przycisku, sprawdź, czy to musi być zmodyfikowany tak, aby wiedział, że ma się zamknąć, przesuwając go w prawo na lewo. To może być myślenie, że menu jest już po lewej stronie (tj. Ukryte), więc nie zamknie się (jeśli to ma sens) ...
KickAss
Chłopaki, ja też robię to samo, ale jeśli użyję laoutDirection = "rtl", to muszę zmienić minSdk na 17, ale moja aplikacja musi obsługiwać API na poziomie 10. Czy możecie mi pomóc, aby moja aplikacja obsługiwała API 10.
Aditya
3

Spójrz na to: slide ExpandableListView w formularzu DrawerLayout od prawej do lewej

Zakładam, że masz zaimplementowaną ActionBarDrawerToggle, sztuczka polega na zastąpieniu onOptionsItemSelected(MenuItem item)metody wewnątrz obiektu ActionBarDrawerToggle za pomocą tego:

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

upewnij się i zadzwoń do tego z onOptionsItemSelected(MenuItem item)poziomu działania:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

return super.onOptionsItemSelected(item);
}

Umożliwi to korzystanie z funkcji przycisku strony głównej. Aby przenieść przycisk na prawą stronę paska akcji, będziesz musiał zaimplementować niestandardowy element akcji, a być może kilka innych rzeczy, aby działał tak, jak chcesz.

d370urn3ur
źródło
3

główny problem z następującym błędem:

nie znaleziono widoku szuflady z grawitacją absolutną LEWA

jest to, że zdefiniowałeś

android:layout_gravity="right"

dla widoku listy po prawej, ale spróbuj otworzyć szufladę od lewej, wywołując tę ​​funkcję:

mDrawerToggle.syncState();

i klikając ikonę hamburgera!

po prostu skomentuj powyższą funkcję i spróbuj obsłużyć otwieranie / zamykanie menu, tak jak powiedział @Rudi!

par4301
źródło
3

Rozwiązałem ten problem, zmieniając wagę widoku nawigacji

android: layout_gravity

do końca zamiast od początku

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

U mnie to zadziałało.

Abdulaziz Alnahhas
źródło
2

Najpierw należy umieścić ten kod w swoim AppManifest.xml w tagu aplikacji:

android:supportsRtl="true"

następnie w pliku activity_main.xml umieść ten fragment kodu:

android:layout_direction="rtl"
Shabnam Esmaeili
źródło
to najlepsze rozwiązanie w historii, oszczędzasz mi dnia dzięki
Ahmed Mousa
2

Zrobiłem następującą modyfikację przykładu działania szuflady nawigacji w Android Studio. Z bibliotekami wsparcia 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 (pobierz ic_menu_white_24px z 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>

W activity_main.xml zmień

android:layout_gravity="start"

do

android:layout_gravity="end"
Mathias Jeppsson
źródło
2

Otwieranie go z rtl nie jest dobre dla wrażenia użytkownika, aby reagować na ustawienia regionalne użytkownika, właśnie dodałem następujący wiersz do moich parametrów DrawerLayout:

android:layoutDirection="locale"

Dodano go do mojego AppBarLayout, aby układ hamburgerów pasował również do kierunku otwierania szuflady.

arbel03
źródło
1

DrawerLayout Właściwości android:layout_gravity="right|end"i tools:openDrawer="end" NavigationView nieruchomości 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);
            }
        }
    });
//...
}
Ashvin solanki
źródło