Como implementar DrawerArrowToggle da biblioteca Android appcompat v7 21

97

Agora que o Android 5.0 foi lançado, eu queria saber como implementar os ícones animados da barra de ações.

Esta biblioteca aqui o implementa bem para mim, mas como a biblioteca appcompat v7 o possui, como pode ser implementado?

A biblioteca faz referência a ele em themes.xml

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

Sob este estilo

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

ATUALIZAR

Implementei isso usando o DrawerToggle v7. No entanto, não posso estilizá-lo. Por favor ajude

Encontrei o estilo dele no 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>

Eu adicionei isso aos meus estilos e não funcionou. Também adicionado ao meu 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>

Mas trava e diz erro de tipo de cor ao fazer isso. O que estou perdendo?

Bignadad
fonte

Respostas:

243

Primeiro, você deve saber agora que o android.support.v4.app.ActionBarDrawerToggleestá obsoleto.

Você deve substituir isso por android.support.v7.app.ActionBarDrawerToggle.

Aqui está meu exemplo e uso o novo Toolbarpara substituir o 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>

Você pode ler os documentos em AndroidDocument # DrawerArrowToggle_spinBars

Este atributo é a chave para implementar a animação menu-seta.

public static int DrawerArrowToggle_spinBars

Se as barras devem girar ou não durante a transição
Deve ser um valor booleano, "verdadeiro" ou "falso".

Então, você define esse: <item name="spinBars">true</item>.

Em seguida, a animação pode ser apresentada.

Espero que isso possa ajudá-lo.

Yong
fonte
12
Tive problemas para exibir o ícone do hambúrguer. chamar mDrawerToggle.syncState();consertou.
aheuermann
1
para mim getSupportActionBar () retorna null .. qual poderia ser o motivo?
Ramesh_D
2
Android Studio diz Cannot resolve method setSupportActionBar(android.widget.Toolbar). Eu também tentei com android.support.v7.toolbar. Alguém sabe por que isso acontece?
pez
1
Usei setSupportActionBar(mToolbar);e também defini, <item name="spinBars">true</item>mas a animação não está funcionando
SweetWisher ツ
2
Deve usar ActionBarDrawerToggle (Activity, DrawerLayout, int, int) se você estiver definindo a barra de ferramentas como a ActionBar de sua atividade.
Peter Zhao
24

Se estiver usando o DrawerLayout fornecido pela Biblioteca de Suporte, conforme sugerido no treinamento Criando uma gaveta de navegação , você pode usar o android.support recém-adicionado . v7 .app.ActionBarDrawerToggle (observação: diferente do agora obsoleto android.support. v4 .app.ActionBarDrawerToggle ):

mostra um ícone de Hambúrguer quando a gaveta está fechada e uma seta quando a gaveta está aberta. Ele se anima entre esses dois estados conforme a gaveta é aberta.

Embora o treinamento não tenha sido atualizado para levar em consideração a depreciação / nova classe, você deve ser capaz de usá-lo quase exatamente o mesmo código - a única diferença na implementação é o construtor.

ianhanniballake
fonte
Estou usando o v4 no meu aplicativo bc, não preciso oferecer suporte a dispositivos anteriores ao api 15. Então, se eu quisesse que isso funcionasse, eu teria que usar o botão de alternância da gaveta da barra de ação v7? Se eu fizesse isso, não teria que converter todos os meus estilos em AppCompat e fragmentar atividades em atividades da barra de ação e assim por diante? Ou posso implementar apenas a alternância de gaveta da v7. Agora eu uso a v7 para visualizações de cartão. Devo usar v4 se não for compatível com API abaixo de 15? E acho que preciso da v7 para as visualizações de cartão.
Bignadad,
Toda a compatibilidade da Biblioteca de Suporte para Material design é implementada em v7-appcompat e é recomendada se você deseja oferecer suporte a esse estilo em dispositivos <5.0. O AppCompat é desenvolvido e requer a v4, portanto, depende realmente se você deseja usar o AppCompat. Se você já estiver usando FragmentActivity, você já está bem perto - a diferença no estilo é bem pequena agora (principalmente substituindo os atributos android: por atributos sem namespace).
ianhanniballake
Atualizou a pergunta se você não se importasse de dar uma olhada
Bignadad
Essa é realmente uma questão totalmente separada sobre estilo. Eu sugiro enviar essa parte como uma outra pergunta (fique à vontade para adicionar um comentário com um link).
ianhanniballake
1
@mraviator - sim: altere o XML e, em seguida, crie e anexe a v7 ActionBarDrawerToggle. A resposta canônica do criador do AppCompat tem um exemplo completo de como seu XML deve ser estruturado.
ianhanniballake
17

Eu criei um pequeno aplicativo que tinha uma funcionalidade semelhante

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

Meu XML dessa atividade

<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 da minha barra de ferramentas 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>

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

Meus estilos em 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>
tim
fonte
1
Isso funciona perfeitamente, mas eu não quero usar o título, então como posso lidar com isso? Porque se eu usar Theme.AppCompat.Light.NoActionBar , ele definitivamente vai me dar NULL em getSupportActionBar
SweetWisher ツ
Usei o código acima. I got Exception: This Activity já tem uma barra de ação fornecida pela janela decor na linha setsupportactionbar (barra de ferramentas). Usei getSupportActionBar (). Hide (); Antes de setContentView (R.layout.activity_main); Agora está funcionando.
Thirumalvalavan
setSupportActionBar (barra de ferramentas); também comentou.
Thirumalvalavan
9

Para responder à parte atualizada da sua pergunta: para estilizar o ícone / seta da gaveta, você tem duas opções:

Defina o estilo da própria seta

Para fazer isso, substitua drawerArrowStyleem seu tema assim:

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

Provavelmente não é isso que você deseja , porque a própria ActionBar deve ter um estilo consistente com a seta, então, provavelmente, você deseja a opção dois:

Tema a ActionBar / Toolbar

Substitua o atributo android:actionBarTheme( actionBarThemefor appcompat) do tema do aplicativo global por seu próprio tema (do qual você provavelmente deve derivar ThemeOverlay.Material.ActionBar/ThemeOverlay.AppCompat.ActionBar) assim:

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

Uma observação importante aqui é que ao usar um layout personalizado com uma Toolbarimplementação ActionBar em vez de estoque (por exemplo, se você estiver usando a combinação DrawerLayout- NavigationView- Toolbarpara obter o efeito de gaveta de estilo de material onde é visível sob a barra de status translúcida), o actionBarThemeatributo obviamente não escolhido automaticamente (porque deve ser cuidado pelo AppCompatActivitypadrão ActionBar), portanto, para o seu costume Toolbar, não se esqueça de aplicar o tema manualmente:

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

- isso resolverá o padrão do AppCompat ThemeOverlay.AppCompat.ActionBarou a sua substituição se você definir o atributo em seu tema derivado.

PS, um pequeno comentário sobre a drawerArrowStylesubstituição e o spinBarsatributo - que várias fontes sugerem que deve ser definido truepara obter a animação da gaveta / seta. Coisa é, spinBarsé true por padrão no AppCompat (confira o Base.Widget.AppCompat.DrawerArrowToggle.Commonestilo), você não tem que substituir actionBarThemeem tudo para obter o trabalho de animação. Você obtém a animação mesmo se substituí-la e definir o atributo como false, é apenas uma animação diferente, menos sinuosa. O importante aqui é usar ActionBarDrawerToggle, é o que puxa o desenho animado extravagante.

Ivan Bartsov
fonte
2

Eu quero corrigir um pouco o código acima

    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 todas as outras coisas permanecerão iguais ...

Para aqueles que estão tendo problemas para Drawerlayoutsobrepor a barra de ferramentas

adicionar android:layout_marginTop="?attr/actionBarSize"ao layout raiz do conteúdo da gaveta

Nitin Misra
fonte
como você usa getSupportActionBar()quando apenas estende Activity?
wzieba
simplesmente você não pode, você deve estender deActionBarActivity
Nitin Misra