Come impostare il cassetto di navigazione in modo che venga aperto da destra a sinistra


86

Prima di tutto so che questa domanda è apparsa qui prima, ma dopo aver provato molto non ci sono ancora riuscito. Sto lavorando all'esempio dal sito degli sviluppatori Android .

Sto cercando di impostare il menu in modo che venga aperto da destra a sinistra invece di come è implementato nell'esempio (da sinistra a destra). Inoltre, voglio spostare il pulsante del menu aperto sul lato destro della barra delle azioni. Ho anche rosso alcune risposte qui, ad esempio in questa risposta .

Provo a cambiare la gravità delle viste e dei layout ma ottengo l'errore:

nessuna vista cassetto trovata con gravità assoluta SINISTRA

Potete aiutarmi a capire qual è il problema nel mio codice e cosa dovrei cambiare per impostare il menu in modo che venga aperto da destra e per spostare il pulsante della barra delle azioni a destra?

il codice xml è qui:

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


Dai un'occhiata a github.com/Ali-Rezaei/SlidingDrawer che rende possibile scorrere da qualsiasi lato con poche righe di codice.
Ali

Si prega di consultare la risposta stackoverflow.com/a/44076363/5332645
Aman Saxena

Risposte:


155

Nel layout principale imposta la ListViewgravità a destra:

android:layout_gravity="right" 

Anche nel tuo codice:

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

spero funzioni :)


2
@Rudi: conosci la risposta della seconda parte? Intendo come rendere la barra delle azioni da destra a sinistra. (Cambiano anche la direzione del cassetto e dell'icona di navigazione in alto)
Alireza Farahani

@alireza perché non usi una barra delle azioni personalizzata?
Rudi

@Rudi: intendi setCustomViewmetodo? Se sì, ti dispiacerebbe incollare alcuni link che mostrano come farlo?
Alireza Farahani

@alireza Intendevo, invece di usare la barra delle azioni nella parte superiore della visualizzazione, crea la tua barra delle azioni personalizzata nel tuo xml principale e configurala come desideri.
Rudi

@Rudi: Ma allora, come posso ottenere lo stesso comportamento come la navigazione su e l'animazione di apertura e chiusura del cassetto? Devo implementarli da zero?
Alireza Farahani

62

Aggiungi questo codice a manifest:

<application android:supportsRtl="true">

e poi scrivi questo codice su Oncreate:

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

Per me funziona. ;)


1
questa è la risposta corretta, imposta la gravità della tua listview per iniziare, quindi usa questo codice, tutto dovrebbe andare bene
Mahdi Giveie

9
Funziona, tuttavia, setLayoutDirection (View.LAYOUT_DIRECTION_RTL) è per API superiori a 17, quindi non è possibile utilizzarlo per API inferiori
Milad

6
Questo non capovolge l'intero layout dell'attività, anche toStartOf / toEndOf, ecc ...?
TWiStErRob

14
Questa è la risposta sbagliata. Capovolge l'intero layout dell'attività da destra a sinistra.
Tarun

1
Ho pensato che fosse una soluzione rapida ma non corretta.
sidhanshu

37

SOLUZIONE


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
Funziona alla grande. Ma l'icona della barra degli strumenti appare ancora a sinistra. Come portare anche l'icona del pulsante di attivazione / disattivazione a destra?
Darush

ho dato android: layout_gravity = "end" sia per Drawerlayout che per NavigationView, funziona bene.
varotariya vajsi

toolbar.setNavigationOnClickListenerRichiede un livello
API

@ SepJaPro2.4 sì, ma 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
Aggiungi android: layoutDirection = "rtl" nel tuo AppBarLayout XML per impostare il pulsante di
attivazione /

4

Questa risposta è utile per impostare la navigazione in modo che sia aperta da destra a sinistra, ma non ha alcuna soluzione per impostare la sua icona sul lato destro. Questo codice può risolverlo. Se gli dai drawercome primo parametro e ViewCompat.LAYOUT_DIRECTION_RTLcome secondo parametro, il layout completo verrà impostato su RTL. È una soluzione rapida e semplice, ma non credo possa essere una soluzione corretta per chi vuole impostare solo il menu in modo che sia aperto da destra verso sinistra e impostare la sua icona in modo che sia sul lato destro. (Anche se dipende dal tuo scopo.) Tuttavia, ti suggerisco di dare il toolbarinvece di drawer. In questo modo solo la barra degli strumenti è diventata RTL. Quindi penso che la combinazione di queste 2 risposte possa fare esattamente quello che vuoi.

Secondo queste descrizioni, il tuo codice dovrebbe essere così:

(Aggiungi queste righe al metodo 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);
        }
    });

Nota che dovresti rendere il cassetto finale, altrimenti otterrai questo errore:

Si accede alla variabile 'drawer' dall'interno della classe interna, deve essere dichiarata final

E non dimenticare di usare endal posto di startin onNavigationItemSelectedmetodo:

drawer.closeDrawer(GravityCompat.END);

e nel tuo 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

Ecco la documentazione sul cassetto e sembra che tu possa configurarlo per estrarlo da sinistra o da destra.

Il posizionamento e il layout del cassetto sono controllati utilizzando l'attributo android: layout_gravity nelle viste figlie corrispondenti al lato della vista da cui vuoi che esca il cassetto: sinistra o destra. (Oppure inizio / fine sulle versioni della piattaforma che supportano la direzione del layout.)

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


Ho già visto questa risposta e l'ho anche menzionata nella mia domanda.
galvan il

Va bene. Prova a usare endinvece che rightin gravità. EDIT: Rimuovere android:layout_gravity="right"dal android.support...DrawerLayoute il cambiamento android:layout_gravity="right"di android:layout_gravity="end"dentroListView
KickAss

1
Ho ancora ricevuto l'errore: nessuna vista del cassetto trovata con gravità assoluta a SINISTRA. Ho aggiunto al manifest android: supportsRtl = "true", e nell'xml sotto drawerLayout ho aggiunto android: layoutDirection = "rtl", quindi il menu si apre a destra, ma ora non si chiude quando premo il pulsante pulsante menu (nella barra delle azioni) quando clicco su qualsiasi elemento nell'elenco, o al di fuori dell'elenco si chiude ma no quando tocco il pulsante menu nella barra delle azioni, qualche idea perché?
galvan il

Non sono del tutto sicuro, ma ... poiché la direzione e la posizione del cassetto ora sono cambiate, nella tua attività, come nell'esempio di Android, dovresti avere il metodo di commutazione / listener del pulsante, controlla se deve essere modificato in modo che sappia chiudersi spostandolo RightToLeft. Potrebbe pensare che il menu di attesa sia già a sinistra (cioè nascosto), quindi non si chiuderà (se ha senso) ...
KickAss

Ragazzi, anch'io sto facendo lo stesso genere di cose, ma se uso laoutDirection = "rtl" allora devo cambiare minSdk come 17 ma la mia app deve supportare il livello API 10. Ragazzi, potete aiutarmi in modo che la mia app possa supportare API 10.
Aditya

3

Dai un'occhiata a questo: fai scorrere ExpandableListView nel modulo DrawerLayout da destra a sinistra

Presumo che tu abbia implementato ActionBarDrawerToggle, il trucco è sovrascrivere il onOptionsItemSelected(MenuItem item)metodo all'interno dell'oggetto ActionBarDrawerToggle con questo:

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

assicurati di chiamarlo dall'attività onOptionsItemSelected(MenuItem item):

@Override
public boolean onOptionsItemSelected(MenuItem item) {

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

return super.onOptionsItemSelected(item);
}

Ciò ti consentirà di utilizzare la funzionalità del pulsante home. Per spostare il pulsante sul lato destro della barra delle azioni dovrai implementare un elemento di azione personalizzato e forse qualche altra cosa per farlo funzionare come desideri.


3

il problema principale con il seguente errore:

nessuna vista cassetto trovata con gravità assoluta SINISTRA

è così, hai definito il file

android:layout_gravity="right"

per la visualizzazione elenco a destra, ma prova ad aprire il cassetto da sinistra, chiamando questa funzione:

mDrawerToggle.syncState();

e cliccando sull'icona dell'hamburger!

basta commentare la funzione sopra e provare a gestire l'apertura / chiusura del menu come ha detto @Rudi!


3

Ho risolto questo problema modificando la gravità della visualizzazione di navigazione

android: layout_gravity

per finire invece di iniziare

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

Ha funzionato per me.


2

Dovresti prima inserire questo codice nel tuo AppManifest.xml nel tag dell'applicazione:

android:supportsRtl="true"

quindi nel tuo file activity_main.xml, inserisci questo pezzo di codice:

android:layout_direction="rtl"

questa è la soluzione migliore in assoluto, mi salvi la giornata grazie
Ahmed Mousa

2

Ho apportato le seguenti modifiche all'esempio di attività del riquadro di navigazione in Android Studio. Con le librerie di supporto 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 (scarica ic_menu_white_24px da 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>

In activity_main.xml cambia

android:layout_gravity="start"

per

android:layout_gravity="end"

2

Renderlo aperto da rtl non è positivo per l'esperienza dell'utente, per renderlo reattivo alle impostazioni locali dell'utente ho appena aggiunto la seguente riga ai miei parametri DrawerLayout:

android:layoutDirection="locale"

Aggiunto al mio AppBarLayout per fare in modo che il layout dell'hamburger corrisponda anche alla direzione di apertura del cassetto.


1

Proprietà DrawerLayoutandroid:layout_gravity="right|end" e proprietà 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);
            }
        }
    });
//...
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.