Comment implémenter DrawerArrowToggle à partir de la bibliothèque Android appcompat v7 21

97

Alors maintenant qu'Android 5.0 est sorti, je me demandais comment implémenter les icônes de la barre d'action animée.

Cette bibliothèque l' implémente ici très bien pour moi, mais puisque la bibliothèque appcompat v7 l'a, comment peut-elle être implémentée?

La bibliothèque y fait référence dans themes.xml

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

Sous ce style

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

METTRE À JOUR

Je l'ai implémenté en utilisant le DrawerToggle v7. Cependant, je ne peux pas le styliser. Veuillez aider

J'ai trouvé le style pour cela dans le 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>

J'ai ajouté cela à mes styles et je n'ai pas fonctionné. Également ajouté à mon 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>

Mais se bloque et dit une erreur de type de couleur en le faisant. Qu'est-ce que je rate?

Bignadad
la source

Réponses:

243

Tout d'abord, vous devez savoir maintenant que le android.support.v4.app.ActionBarDrawerToggleest obsolète.

Vous devez le remplacer par android.support.v7.app.ActionBarDrawerToggle.

Voici mon exemple et j'utilise le nouveau Toolbarpour remplacer le 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>

Vous pouvez lire les documents sur AndroidDocument # DrawerArrowToggle_spinBars

Cet attribut est la clé pour implémenter l'animation menu-flèche.

public static int DrawerArrowToggle_spinBars Indique

si les barres doivent tourner ou non pendant la transition
Doit être une valeur booléenne, "true" ou "false".

Donc, vous définissez ceci: <item name="spinBars">true</item>.

Ensuite, l'animation peut être présentée.

J'espère que cela peut vous aider.

Yong
la source
12
J'ai rencontré des problèmes pour afficher l'icône du hamburger. l'appel l'a mDrawerToggle.syncState();corrigé.
aheuermann
1
pour moi getSupportActionBar () renvoie null .. quelle pourrait en être la raison?
Ramesh_D
2
Dit Android Studio Cannot resolve method setSupportActionBar(android.widget.Toolbar). J'ai aussi essayé avec android.support.v7.toolbar. Est-ce que quelqu'un sait pourquoi cela se produit?
pez
1
J'ai utilisé setSupportActionBar(mToolbar);et aussi défini <item name="spinBars">true</item>mais l'animation ne fonctionne pas
SweetWisher ツ
2
Vous devez utiliser ActionBarDrawerToggle (Activity, DrawerLayout, int, int) si vous définissez la barre d'outils comme ActionBar de votre activité.
Peter Zhao
24

Si vous utilisez la bibliothèque de support fournie DrawerLayout comme suggéré dans la formation Création d'un tiroir de navigation , vous pouvez utiliser le nouveau fichier android.support. v7 .app.ActionBarDrawerToggle (note: différent de android.support. v4 .app.ActionBarDrawerToggle désormais obsolète ):

affiche une icône Hamburger lorsque le tiroir est fermé et une flèche lorsque le tiroir est ouvert. Il s'anime entre ces deux états lorsque le tiroir s'ouvre.

Bien que la formation n'ait pas été mise à jour pour prendre en compte la dépréciation / la nouvelle classe, vous devriez pouvoir l'utiliser presque exactement le même code - la seule différence dans sa mise en œuvre est le constructeur.

ianhanniballake
la source
J'utilise la v4 dans mon application bc je n'ai pas besoin de prendre en charge les appareils antérieurs à l'API 15. Donc, si je voulais que cela fonctionne, je devrais utiliser la bascule du tiroir de la barre d'action v7? Si je faisais cela, ne devrais-je pas convertir tous mes styles en AppCompat et fragmenter les activités en activités de la barre d'action, etc. Ou puis-je implémenter uniquement la bascule Drawer de la v7. En ce moment, j'utilise la v7 pour les vues de cartes. Dois-je même utiliser la v4 si je ne supporte pas les API inférieures à 15? Et je suppose que j'ai besoin de la version 7 pour les vues de carte.
Bignadad
Toute la compatibilité de la bibliothèque de support pour la conception de matériaux est implémentée dans v7-appcompat et est recommandée si vous souhaitez prendre en charge ce style sur les appareils <5.0. AppCompat est construit à partir de et nécessite la v4, donc c'est vraiment le cas si vous voulez utiliser AppCompat. Si vous utilisez déjà FragmentActivity, vous êtes déjà assez proche - la différence de style est assez petite maintenant (principalement en remplaçant simplement les attributs android: avec des attributs sans espace de nom).
ianhanniballake
Mise à jour de la question si cela ne vous dérange pas de jeter un coup d'œil s'il vous plaît
Bignadad
C'est vraiment une toute autre question sur le style. Je suggérerais de soumettre cette partie comme une toute autre question (n'hésitez pas à ajouter un commentaire avec un lien vers elle).
ianhanniballake
1
@mraviator - oui: changez XML, puis créez et attachez le v7 ActionBarDrawerToggle. La réponse canonique du créateur d'AppCompat a un exemple complet de la manière dont votre XML doit être structuré.
ianhanniballake
17

J'ai créé une petite application qui avait des fonctionnalités similaires

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

Mon XML de cette activité

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

Ma barre d'outils personnalisée 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>

Mon style de thème

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

Mes styles dans 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>
Tim
la source
1
Cela fonctionne parfaitement mais je ne veux pas utiliser Title, alors comment puis-je gérer cela? Parce que si j'utilise Theme.AppCompat.Light.NoActionBar , cela me donnera certainement NULL à getSupportActionBar
SweetWisher ツ
J'ai utilisé le code ci-dessus. J'ai une exception: cette activité a déjà une barre d'action fournie par le décor de fenêtre dans la ligne setsupportactionbar (barre d'outils). J'ai utilisé getSupportActionBar (). Hide (); Avant setContentView (R.layout.activity_main); Maintenant ça marche.
Thirumalvalavan
setSupportActionBar (barre d'outils); a également commenté.
Thirumalvalavan
9

Pour répondre à la partie mise à jour de votre question: pour styliser l'icône / la flèche du tiroir, vous avez deux options:

Style de la flèche elle-même

Pour ce faire, remplacez drawerArrowStylevotre thème comme suit:

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

Ce n'est probablement pas ce que vous voulez , car l'ActionBar lui-même devrait avoir un style cohérent avec la flèche, donc, très probablement, vous voulez l'option deux:

Thème l'ActionBar / Toolbar

Remplacez l' attribut android:actionBarTheme( actionBarThemefor appcompat) du thème d'application global avec votre propre thème (dont vous devriez probablement dériver ThemeOverlay.Material.ActionBar/ThemeOverlay.AppCompat.ActionBar) comme suit:

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

Une note importante ici est que lorsque vous utilisez une mise en page personnalisée avec une Toolbarimplémentation ActionBar au lieu de stock (par exemple, si vous utilisez le combo DrawerLayout- NavigationView- Toolbarpour obtenir l'effet de tiroir de style Material là où il est visible sous la barre d'état translucide), l' actionBarThemeattribut n'est évidemment pas ramassé automatiquement (car il est censé être pris en charge par le AppCompatActivitypar défaut ActionBar), donc pour votre personnalisation, Toolbarn'oubliez pas d'appliquer votre thème manuellement:

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

- cela résoudra soit la valeur par défaut d'AppCompat, ThemeOverlay.AppCompat.ActionBarsoit votre remplacement si vous définissez l'attribut dans votre thème dérivé.

PS un petit commentaire sur le drawerArrowStyleremplacement et l' spinBarsattribut - que de nombreuses sources suggèrent qu'il devrait être réglé truepour obtenir l'animation tiroir / flèche. Le fait est que spinBarsc'est true par défaut dans AppCompat (vérifiez le Base.Widget.AppCompat.DrawerArrowToggle.Commonstyle), vous n'avez pas du tout à remplacer actionBarThemepour que l'animation fonctionne. Vous obtenez l'animation même si vous la remplacez et définissez l'attribut sur false, c'est juste une animation différente, moins sinueuse. L'important ici est d'utiliser ActionBarDrawerToggle, c'est ce qui attire le dessin animé fantaisie.

Ivan Bartsov
la source
2

Je veux corriger un peu le code ci-dessus

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

et toutes les autres choses resteront les mêmes ...

Pour ceux qui ont des problèmes de Drawerlayoutsuperposition de la barre d'outils

ajouter android:layout_marginTop="?attr/actionBarSize"à la disposition racine du contenu du tiroir

Nitin Misra
la source
comment vous utilisez getSupportActionBar()quand vous venez de prolonger Activity?
wzieba
tout simplement vous ne pouvez pas, vous devez prolonger deActionBarActivity
Nitin Misra