Cómo implementar DrawerArrowToggle desde la biblioteca appcompat v7 21 de Android


97

Entonces, ahora que se lanzó Android 5.0, me preguntaba cómo implementar los íconos animados de la barra de acción.

Esta biblioteca aquí lo implementa bien para mí, pero dado que la biblioteca appcompat v7 lo tiene, ¿cómo se puede implementar?

La biblioteca lo hace referencia en themes.xml

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

Bajo este estilo

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

ACTUALIZAR

Conseguí esto implementado usando el v7 DrawerToggle. Sin embargo, no puedo diseñarlo. Por favor ayuda

Encontré el estilo en v7 styles_base.xml

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

Agregué esto a mis estilos y no funcionó. También agregado a mi 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>

Pero se bloquea y dice un error de tipo de color al hacerlo. ¿Qué me estoy perdiendo?

Respuestas:


243

Primero, debe saber que ahora android.support.v4.app.ActionBarDrawerToggleestá obsoleto.

Debes reemplazar eso con android.support.v7.app.ActionBarDrawerToggle.

Aquí está mi ejemplo y utilizo el nuevo Toolbarpara reemplazar el 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>

Puede leer los documentos en AndroidDocument # DrawerArrowToggle_spinBars

Este atributo es la clave para implementar la animación de menú a flecha.

public static int DrawerArrowToggle_spinBars

Si las barras deben rotar o no durante la transición
Debe ser un valor booleano, ya sea "verdadero" o "falso".

Así, se establece lo siguiente: <item name="spinBars">true</item>.

Entonces se puede presentar la animación.

Espero que esto le pueda ayudar.


12
Tuve problemas para que apareciera el icono de la hamburguesa. llamar lo mDrawerToggle.syncState();arregló.
aheuermann

1
para mí getSupportActionBar () devuelve nulo ... ¿cuál podría ser la razón?
Ramesh_D

2
Android Studio dice Cannot resolve method setSupportActionBar(android.widget.Toolbar). También he probado con android.support.v7.toolbar. ¿Alguien sabe por qué sucede esto?
pez

1
He utilizado setSupportActionBar(mToolbar);y definido <item name="spinBars">true</item>, pero la animación no funciona
SweetWisherツ

2
Debe usar ActionBarDrawerToggle (Activity, DrawerLayout, int, int) si está configurando la barra de herramientas como la barra de acciones de su actividad.
Peter Zhao

24

Si está utilizando el DrawerLayout proporcionado por la biblioteca de soporte como se sugiere en la capacitación Creación de un cajón de navegación , puede usar el android.support recién agregado . v7 .app.ActionBarDrawerToggle (nota: diferente del ahora obsoleto android.support. v4 .app.ActionBarDrawerToggle ):

muestra un icono de hamburguesa cuando el cajón está cerrado y una flecha cuando el cajón está abierto. Se anima entre estos dos estados cuando se abre el cajón.

Si bien el entrenamiento no se ha actualizado para tener en cuenta la obsolescencia / nueva clase, debería poder usarlo casi exactamente el mismo código; la única diferencia en la implementación es el constructor.


Estoy usando v4 en mi aplicación porque no necesito admitir dispositivos antes de la API 15. Entonces, si quisiera que esto funcionara, tendría que usar la palanca del cajón de la barra de acciones v7. Si hiciera eso, ¿no tendría que convertir todos mis estilos a AppCompat y fragmentar las actividades en actividades de la barra de acciones, etc.? ¿O puedo implementar solo el interruptor de cajón de v7. Ahora mismo utilizo v7 para las vistas de tarjetas. ¿Debería incluso usar v4 si no soy compatible con una API por debajo de 15? Y supongo que necesito v7 para las vistas de la tarjeta.
Bignadad

Toda la compatibilidad de la biblioteca de compatibilidad para el diseño de materiales se implementa en v7-appcompat y se recomienda si desea admitir ese estilo en dispositivos <5.0. AppCompat se basa en y requiere v4, por lo que realmente está a la altura si desea usar AppCompat. Si ya está usando FragmentActivity, ya está bastante cerca: la diferencia en el estilo es bastante pequeña ahora (principalmente reemplazando los atributos android: con atributos sin espacios de nombres).
ianhanniballake

Se actualizó la pregunta si no le importaría echar un vistazo, por favor
Bignadad

Esa es realmente una pregunta completamente separada sobre el estilo. Sugeriría enviar esa parte como una pregunta completamente diferente (siéntase libre de agregar un comentario con un enlace).
ianhanniballake

1
@mraviator - sí: cambie XML, luego cree y adjunte el archivo v7 ActionBarDrawerToggle. La respuesta canónica del fabricante de AppCompat tiene un ejemplo completo de cómo debe estructurarse su XML.
ianhanniballake

17

Creé una pequeña aplicación que tenía una funcionalidad similar

Actividad principal

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

Mi XML de esa actividad

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

XML de mi barra de herramientas personalizada

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

Mi estilo de 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>

Mis estilos en valores-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
Esto funciona perfectamente, pero no quiero usar el título, ¿cómo puedo manejar esto? Porque si uso Theme.AppCompat.Light.NoActionBar , definitivamente me dará NULL en getSupportActionBar
SweetWisher ツ

Usé el código anterior. Obtuve una excepción: esta actividad ya tiene una barra de acción proporcionada por la decoración de la ventana en la línea setupportactionbar (barra de herramientas). Usé getSupportActionBar (). Hide (); Antes de setContentView (R.layout.activity_main); Ahora está funcionando.
Thirumalvalavan

setSupportActionBar (barra de herramientas); también comentó.
Thirumalvalavan

9

Para responder a la parte actualizada de su pregunta: para diseñar el icono / flecha del cajón, tiene dos opciones:

Estilo de la propia flecha

Para hacer esto, anule drawerArrowStylesu tema así:

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

Probablemente esto no sea lo que desea , porque la barra de acción en sí debería tener un estilo coherente con la flecha, por lo que lo más probable es que desee la opción dos:

Tema de la barra de acciones / barra de herramientas

Anular el android:actionBarTheme( actionBarThemeatributo para appcompat) del tema global solicitud con su propio tema (que probablemente debería derivar de ThemeOverlay.Material.ActionBar/ThemeOverlay.AppCompat.ActionBar) de esta manera:

<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 aquí es que cuando se usa un diseño personalizado con una Toolbarimplementación de ActionBar en lugar de stock (por ejemplo, si está usando el combo DrawerLayout- NavigationView- Toolbarpara lograr el efecto de cajón de estilo Material donde es visible debajo de la barra de estado translúcida), el actionBarThemeatributo obviamente no es recogido automáticamente (porque está destinado a ser atendido por AppCompatActivityel predeterminado ActionBar), por lo que para su personalización Toolbarno olvide aplicar su tema manualmente:

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

- esto se resolverá en el valor predeterminado de AppCompat ThemeOverlay.AppCompat.ActionBaro en su anulación si establece el atributo en su tema derivado.

PD: un pequeño comentario sobre la drawerArrowStyleanulación y el spinBarsatributo, que muchas fuentes sugieren que se debe configurar truepara obtener la animación del cajón / flecha. La cosa es spinBarsque está true por defecto en AppCompat (revisa el Base.Widget.AppCompat.DrawerArrowToggle.Commonestilo), no tienes que anular actionBarThemenada para que la animación funcione. Obtiene la animación incluso si la anula y establece el atributo en false, es solo una animación diferente, menos giratoria. Lo importante aquí es usar ActionBarDrawerToggle, es lo que atrae el elegante dibujo animado.


2

Quiero corregir un poco el código anterior.

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

y todas las demás cosas seguirán igual ...

Para aquellos que tienen problemas para Drawerlayoutsuperponer la barra de herramientas

agregar android:layout_marginTop="?attr/actionBarSize"al diseño raíz del contenido del cajón


¿Cómo lo usas getSupportActionBar()cuando solo extiendes Activity?
wzieba

simplemente no puede, debe extenderse desdeActionBarActivity
Nitin Misra
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.