Come implementare DrawerArrowToggle dalla libreria Android appcompat v7 21


97

Quindi, ora che è stato rilasciato Android 5.0, mi chiedevo come implementare le icone animate della barra delle azioni.

Questa libreria qui lo implementa bene per me, ma dal momento che la libreria appcompat v7 ce l'ha, come può essere implementata?

La libreria fa riferimento ad esso in temi.xml

 <item name="drawerArrowStyle">@style/Widget.AppCompat.DrawerArrowToggle</item>

Sotto questo stile

 <style name="Base.V7.Theme.AppCompat" parent="Platform.AppCompat">

AGGIORNARE

L'ho implementato utilizzando il DrawerToggle v7. Tuttavia non posso modellarlo. Per favore aiuto

Ho trovato lo stile per questo in styles_base.xml v7

<style name="Base.Widget.AppCompat.DrawerArrowToggle" parent="">
    <item name="color">?android:attr/textColorSecondary</item>
    <item name="thickness">2dp</item>
    <item name="barSize">18dp</item>
    <item name="gapBetweenBars">3dp</item>
    <item name="topBottomBarArrowSize">11.31dp</item>
    <item name="middleBarArrowSize">16dp</item>
    <item name="drawableSize">24dp</item>
    <item name="spinBars">true</item>
</style>

L'ho aggiunto ai miei stili e non ha funzionato. Aggiunto anche al mio attr.xml

<declare-styleable name="DrawerArrowToggle">
    <!-- The drawing color for the bars -->
    <attr name="color" format="color"/>
    <!-- Whether bars should rotate or not during transition -->
    <attr name="spinBars" format="boolean"/>
    <!-- The total size of the drawable -->
    <attr name="drawableSize" format="dimension"/>
    <!-- The max gap between the bars when they are parallel to each other -->
    <attr name="gapBetweenBars" format="dimension"/>
    <!-- The size of the top and bottom bars when they merge to the middle bar to form an arrow -->
    <attr name="topBottomBarArrowSize" format="dimension"/>
    <!-- The size of the middle bar when top and bottom bars merge into middle bar to form an arrow -->
    <attr name="middleBarArrowSize" format="dimension"/>
    <!-- The size of the bars when they are parallel to each other -->
    <attr name="barSize" format="dimension"/>
    <!-- The thickness (stroke size) for the bar paint -->
    <attr name="thickness" format="dimension"/>
</declare-styleable>

Ma si blocca e dice errore di tipo di colore quando lo fa. Cosa mi manca?

Risposte:


243

Innanzitutto, dovresti sapere ora che android.support.v4.app.ActionBarDrawerToggleè deprecato.

Devi sostituirlo con android.support.v7.app.ActionBarDrawerToggle.

Ecco il mio esempio e utilizzo il nuovo Toolbarper sostituire il file ActionBar.

MainActivity.java

public class MainActivity extends ActionBarActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(mToolbar);
    DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(
        this,  mDrawerLayout, mToolbar,
        R.string.navigation_drawer_open, R.string.navigation_drawer_close
    );
    mDrawerLayout.setDrawerListener(mDrawerToggle);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeButtonEnabled(true);
    mDrawerToggle.syncState();
}

styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light">
    <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
</style>

<style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
    <item name="spinBars">true</item>
    <item name="color">@android:color/white</item>
</style>

Puoi leggere i documenti su AndroidDocument # DrawerArrowToggle_spinBars

Questo attributo è la chiave per implementare l'animazione da menu a freccia.

public static int DrawerArrowToggle_spinBars

Indica se le barre devono ruotare o meno durante la transizione
Deve essere un valore booleano, "true" o "false".

Quindi, si imposta questo: <item name="spinBars">true</item>.

Quindi l'animazione può essere presentata.

Spero che questo possa aiutarti.


12
Ho riscontrato problemi nel far comparire l'icona dell'hamburger. chiamando lo ha mDrawerToggle.syncState();risolto.
aheuermann

1
per me getSupportActionBar () restituisce null .. quale potrebbe essere il motivo?
Ramesh_D

2
Dice Android Studio Cannot resolve method setSupportActionBar(android.widget.Toolbar). Ho provato anche con android.support.v7.toolbar. Qualcuno sa perché questo accade?
pez

1
Ho usato setSupportActionBar(mToolbar);e anche definito <item name="spinBars">true</item>ma l'animazione non funzionava
SweetWisher ツ

2
Dovresti usare ActionBarDrawerToggle (Activity, DrawerLayout, int, int) se stai impostando la Toolbar come ActionBar della tua attività.
Peter Zhao

24

Se stai utilizzando la libreria di supporto fornita DrawerLayout come suggerito nella formazione sulla creazione di un cassetto di navigazione , puoi utilizzare android.support appena aggiunto . v7 .app.ActionBarDrawerToggle (nota: diverso da android.support. v4 .app.ActionBarDrawerToggle ora deprecato ):

mostra un'icona Hamburger quando il cassetto è chiuso e una freccia quando il cassetto è aperto. Si anima tra questi due stati quando il cassetto si apre.

Sebbene la formazione non sia stata aggiornata per tenere conto della deprecazione / nuova classe, dovresti essere in grado di usarla quasi esattamente con lo stesso codice: l'unica differenza nell'implementazione è il costruttore.


Sto usando la v4 nella mia app bc non ho bisogno di supportare i dispositivi prima dell'api 15. Quindi, se volevo che funzionasse, dovrei usare il comando a scomparsa della barra delle azioni v7? Se lo facessi, non dovrei convertire tutti i miei stili in AppCompat e le attività di frammentazione in attività della barra delle azioni e così via? Oppure posso implementare solo l'interruttore Drawer dalla v7. In questo momento utilizzo la v7 per le visualizzazioni delle schede. Dovrei anche usare la v4 se non sto supportando API inferiori a 15? E immagino di aver bisogno della v7 per le visualizzazioni delle schede.
Bignadad

Tutta la compatibilità della libreria di supporto per Material design è implementata in v7-appcompat ed è consigliata se si desidera supportare tale stile su dispositivi <5.0. AppCompat è costruito e richiede v4, quindi è davvero all'altezza se vuoi usare AppCompat. Se stai già utilizzando FragmentActivity, sei già abbastanza vicino: la differenza nello stile è piuttosto piccola ora (per lo più sostituendo solo gli attributi android: con attributi senza spazio dei nomi).
ianhanniballake

Aggiornata la domanda se non ti dispiace dare un'occhiata per favore
Bignadad

Questa è davvero una domanda completamente separata sullo stile. Suggerirei di inviare quella parte come un'intera altra domanda (sentiti libero di aggiungere un commento con un link ad esso).
ianhanniballake

1
@mraviator - sì: cambia XML, quindi crea e collega il file v7 ActionBarDrawerToggle. La risposta canonica del creatore di AppCompat ha un esempio completo di come dovrebbe essere strutturato il tuo XML.
ianhanniballake

17

Ho creato una piccola applicazione che aveva funzionalità simili

Attività principale

public class MyActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
        android.support.v7.widget.Toolbar toolbar = (android.support.v7.widget.Toolbar) findViewById(R.id.toolbar);
        ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(
                this,
                drawerLayout,
                toolbar,
                R.string.open,
                R.string.close
        )

        {
            public void onDrawerClosed(View view)
            {
                super.onDrawerClosed(view);
                invalidateOptionsMenu();
                syncState();
            }

            public void onDrawerOpened(View drawerView)
            {
                super.onDrawerOpened(drawerView);
                invalidateOptionsMenu();
                syncState();
            }
        };
        drawerLayout.setDrawerListener(actionBarDrawerToggle);

        //Set the custom toolbar
        if (toolbar != null){
            setSupportActionBar(toolbar);
        }

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        actionBarDrawerToggle.syncState();
    }
}

Il mio XML di quell'attività

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MyActivity"
    android:id="@+id/drawer"
    >

    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <include layout="@layout/toolbar_custom"/>
    </FrameLayout>
    <!-- The navigation drawer -->
    <ListView
        android:layout_marginTop="?attr/actionBarSize"
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#457C50"/>


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

La mia barra degli strumenti personalizzata XML

<?xml version="1.0" encoding="utf-8"?>

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/toolbar"
    android:background="?attr/colorPrimaryDark">
    <TextView android:text="U titel"
        android:textAppearance="@android:style/TextAppearance.Theme"
        android:textColor="@android:color/white"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</android.support.v7.widget.Toolbar>

Il mio stile tema

<resources>
    <style name="AppTheme" parent="Base.Theme.AppCompat"/>

    <style name="AppTheme.Base" parent="Theme.AppCompat">
        <item name="colorPrimary">@color/primary</item>
        <item name="colorPrimaryDark">@color/primaryDarker</item>
        <item name="android:windowNoTitle">true</item>
        <item name="windowActionBar">false</item>
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
    </style>

    <style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
        <item name="spinBars">true</item>
        <item name="color">@android:color/white</item>
    </style>

    <color name="primary">#457C50</color>
    <color name="primaryDarker">#580C0C</color>
</resources>

I miei stili in values-v21

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme" parent="AppTheme.Base">
        <item name="android:windowContentTransitions">true</item>
        <item name="android:windowAllowEnterTransitionOverlap">true</item>
        <item name="android:windowAllowReturnTransitionOverlap">true</item>
        <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>
        <item name="android:windowSharedElementExitTransition">@android:transition/move</item>
    </style>
</resources>

1
Funziona perfettamente ma non voglio usare il titolo, quindi come posso gestirlo? Perché se uso Theme.AppCompat.Light.NoActionBar , mi darà sicuramente NULL su getSupportActionBar
SweetWisher ツ

Ho usato il codice sopra. Ho un'eccezione: questa attività ha già una barra delle azioni fornita dall'arredamento della finestra nella riga setsupportactionbar (barra degli strumenti). Ho usato getSupportActionBar (). Hide (); Prima di setContentView (R.layout.activity_main); Adesso funziona.
Thirumalvalavan

setSupportActionBar (barra degli strumenti); ha anche commentato.
Thirumalvalavan

9

Per rispondere alla parte aggiornata della tua domanda: per modellare l'icona / freccia del cassetto, hai due opzioni:

Modella la freccia stessa

Per fare ciò, sovrascrivi il drawerArrowStyletuo tema in questo modo:

<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    <item name="drawerArrowStyle">@style/MyTheme.DrawerArrowToggle</item>
</style>
<style name="MyTheme.DrawerArrowToggle" parent="Widget.AppCompat.DrawerArrowToggle">
    <item name="color">@android:color/holo_purple</item>
    <!-- ^ this will make the icon purple -->
</style>

Questo probabilmente non è quello che vuoi , perché la stessa ActionBar dovrebbe avere uno stile coerente con la freccia, quindi, molto probabilmente, vuoi l'opzione due:

Tema la ActionBar / Toolbar

Sostituisci l' attributo android:actionBarTheme( actionBarThemeper appcompat) del tema dell'applicazione globale con il tuo tema (da cui probabilmente dovresti derivare ThemeOverlay.Material.ActionBar/ThemeOverlay.AppCompat.ActionBar) in questo modo:

<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
    <item name="actionBarTheme">@style/MyTheme.ActionBar</item>
</style>
<style name="MyTheme.ActionBar" parent="ThemeOverlay.AppCompat.ActionBar">
    <item name="android:textColorPrimary">@android:color/white</item>
    <!-- ^ this will make text and arrow white -->
    <!-- you can also override drawerArrowStyle here -->
</style>

Una nota importante qui è che quando si utilizza un layout personalizzato con Toolbarun'implementazione ActionBar invece di quella di serie (ad esempio, se si utilizza la combinazione DrawerLayout- NavigationView- Toolbarper ottenere l'effetto drawer in stile Materiale dove è visibile sotto la barra di stato traslucida), l' actionBarThemeattributo ovviamente non lo è raccolto automaticamente (perché è pensato per essere curato dal AppCompatActivityper impostazione predefinita ActionBar), quindi per la tua personalizzazione Toolbarnon dimenticare di applicare il tuo tema manualmente:

<!--inside your custom layout with DrawerLayout
and NavigationView or whatever -->
<android.support.v7.widget.Toolbar
        ...
        app:theme="?actionBarTheme">

- questo risolverà l'impostazione predefinita di AppCompat ThemeOverlay.AppCompat.ActionBaro il tuo override se imposti l'attributo nel tema derivato.

PS un piccolo commento drawerArrowStylesull'override e sull'attributo spinBars- che molte fonti suggeriscono di impostare trueper ottenere l'animazione del cassetto / freccia. Il fatto è spinBarsche è true di default in AppCompat (controlla lo Base.Widget.AppCompat.DrawerArrowToggle.Commonstile), non devi assolutamente sovrascriverlo actionBarThemeper far funzionare l'animazione. Ottieni l'animazione anche se la sovrascrivi e imposti l'attributo su false, è solo un'animazione diversa, meno tortuosa. La cosa importante qui è da usare ActionBarDrawerToggle, è ciò che attira il disegno animato di fantasia.


2

Voglio correggere un po 'il codice sopra

    public class MainActivity extends ActionBarActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
        DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(
            this,  mDrawerLayout, mToolbar,
            R.string.navigation_drawer_open, R.string.navigation_drawer_close
        );
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
    }

e tutte le altre cose rimarranno le stesse ...

Per coloro che hanno problemi con la Drawerlayoutsovrapposizione della barra degli strumenti

aggiungere android:layout_marginTop="?attr/actionBarSize"al layout radice del contenuto del cassetto


come usi getSupportActionBar()quando estendi Activity?
wzieba

semplicemente non puoi, devi estendere daActionBarActivity
Nitin Misra
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.