So implementieren Sie DrawerArrowToggle aus der Android AppCompat v7 21-Bibliothek

97

Nachdem Android 5.0 veröffentlicht wurde, fragte ich mich, wie ich die animierten Aktionsleistensymbole implementieren sollte.

Diese Bibliothek hier implementiert es gut für mich, aber da die Appcompat v7-Bibliothek es hat, wie kann es implementiert werden?

Die Bibliothek verweist in der Datei themen.xml darauf

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

Unter diesem Stil

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

AKTUALISIEREN

Ich habe dies mit dem v7 DrawerToggle implementiert. Ich kann es jedoch nicht stylen. Bitte helfen Sie

Ich fand das Styling dafür in der 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>

Ich habe dies zu meinen Stilen hinzugefügt und nicht funktioniert. Auch zu meiner attr.xml hinzugefügt

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

Aber stürzt ab und sagt dabei einen Farbtypfehler. Was vermisse ich?

Bignadad
quelle

Antworten:

243

Zuerst sollten Sie jetzt wissen, dass das android.support.v4.app.ActionBarDrawerToggleveraltet ist.

Sie müssen das durch ersetzen android.support.v7.app.ActionBarDrawerToggle.

Hier ist mein Beispiel und ich benutze das Neue Toolbar, um das zu ersetzen 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>

Sie können die Dokumente auf AndroidDocument # DrawerArrowToggle_spinBars lesen

Dieses Attribut ist der Schlüssel zum Implementieren der Animation von Menü zu Pfeil.

public static int DrawerArrowToggle_spinBars Gibt an,

ob Balken während des Übergangs gedreht werden sollen oder nicht.
Muss ein boolescher Wert sein, entweder "true" oder "false".

Also stellen Sie Folgendes ein : <item name="spinBars">true</item>.

Dann kann die Animation präsentiert werden.

Hoffe das kann dir helfen.

Yong
quelle
12
Ich hatte Probleme, das Hamburger-Symbol anzuzeigen. Anruf mDrawerToggle.syncState();behoben.
Aheuermann
1
Für mich gibt getSupportActionBar () null zurück. Was könnte der Grund sein?
Ramesh_D
2
Android Studio sagt Cannot resolve method setSupportActionBar(android.widget.Toolbar). Ich habe es auch mit versucht android.support.v7.toolbar. Weiß jemand warum das passiert?
Pez
1
Ich habe verwendet setSupportActionBar(mToolbar);und auch definiert, <item name="spinBars">true</item>aber Animation funktioniert nicht
SweetWisher ツ
2
Sollte ActionBarDrawerToggle (Activity, DrawerLayout, int, int) verwenden, wenn Sie die Symbolleiste als ActionBar Ihrer Aktivität festlegen.
Peter Zhao
24

Wenn Sie das von der Support Library bereitgestellte DrawerLayout verwenden, wie in der Schulung zum Erstellen einer Navigationsschublade vorgeschlagen , können Sie den neu hinzugefügten android.support verwenden. v7 .app.ActionBarDrawerToggle (Hinweis: unterscheidet sich von dem jetzt veralteten android.support. v4 .app.ActionBarDrawerToggle ):

zeigt ein Hamburger-Symbol bei geschlossener Schublade und einen Pfeil bei geöffneter Schublade. Es wird zwischen diesen beiden Zuständen animiert, wenn die Schublade geöffnet wird.

Obwohl das Training nicht aktualisiert wurde, um die veraltete / neue Klasse zu berücksichtigen, sollten Sie in der Lage sein, fast genau denselben Code zu verwenden - der einzige Unterschied bei der Implementierung ist der Konstruktor.

ianhanniballake
quelle
Ich verwende v4 in meiner App, da ich Geräte vor API 15 nicht unterstützen muss. Wenn ich also wollte, dass dies funktioniert, müsste ich den Schalter für die v7-Aktionsleiste verwenden? Wenn ich das tun würde, müsste ich dann nicht alle meine Stile in AppCompat konvertieren und Aktivitäten in Actionbar-Aktivitäten usw. fragmentieren? Oder kann ich nur den Drawer-Toggle von Version 7 implementieren? Im Moment benutze ich v7 für Kartenansichten. Sollte ich überhaupt v4 verwenden, wenn ich keine API unter 15 unterstütze? Und ich denke, ich brauche v7 für die Kartenansichten.
Bignadad
Die gesamte Support Library-Kompatibilität für das Materialdesign ist in v7-appcompat implementiert und wird empfohlen, wenn Sie dieses Styling auf <5.0-Geräten unterstützen möchten. AppCompat basiert auf und erfordert v4, sodass es wirklich an Ihnen liegt, ob Sie AppCompat überhaupt verwenden möchten. Wenn Sie FragmentActivity bereits verwenden, sind Sie bereits ziemlich nah dran - der Unterschied im Styling ist jetzt ziemlich gering (meistens werden nur die Attribute android: durch Attribute ohne Namensraum ersetzt).
Ianhanniballake
Die Frage wurde aktualisiert, wenn es Ihnen nichts ausmacht, einen Blick darauf zu werfen
Bignadad
Das ist wirklich eine ganz andere Frage zum Styling. Ich würde vorschlagen, diesen Teil als eine ganz andere Frage einzureichen (Sie können gerne einen Kommentar mit einem Link dazu hinzufügen).
Ianhanniballake
1
@mraviator - yep: XML ändern, dann die v7 erstellen und anhängen ActionBarDrawerToggle. Die kanonische Antwort des Herstellers von AppCompat enthält ein vollständiges Beispiel für die Struktur Ihres XML.
Ianhanniballake
17

Ich habe eine kleine Anwendung mit ähnlichen Funktionen erstellt

Hauptaktivität

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

Mein XML dieser Aktivität

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

Meine benutzerdefinierte Symbolleiste 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>

Mein Themenstil

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

Meine Stile 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>
tim
quelle
1
Dies funktioniert perfekt, aber ich möchte Title nicht verwenden. Wie kann ich damit umgehen? Denn wenn ich Theme.AppCompat.Light.NoActionBar verwende , gibt es mir definitiv NULL bei getSupportActionBar
SweetWisher
Ich habe den obigen Code verwendet. Ich habe eine Ausnahme erhalten: Diese Aktivität verfügt bereits über eine Aktionsleiste, die vom Fensterdekor in der Zeile setsupportactionbar (Symbolleiste) bereitgestellt wird. Ich habe getSupportActionBar () verwendet. Hide (); Vor setContentView (R.layout.activity_main); Jetzt funktioniert es.
Thirumalvalavan
setSupportActionBar (Symbolleiste); auch kommentiert.
Thirumalvalavan
9

Um den aktualisierten Teil Ihrer Frage zu beantworten: Um das Schubladen-Symbol / den Schub zu formatieren, haben Sie zwei Möglichkeiten:

Gestalte den Pfeil selbst

Überschreiben Sie dazu drawerArrowStyleIhr Thema wie folgt:

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

Dies ist wahrscheinlich nicht das, was Sie wollen , da die ActionBar selbst ein konsistentes Design mit dem Pfeil haben sollte, also möchten Sie höchstwahrscheinlich die Option zwei:

Theme die ActionBar / Symbolleiste

Überschreiben Sie die android:actionBarTheme( actionBarThemefür appcompat) Attribut der globalen Anwendung Thema mit Ihrem eigenen Thema (die Sie wahrscheinlich aus ableiten sollte ThemeOverlay.Material.ActionBar/ThemeOverlay.AppCompat.ActionBarwie so):

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

Ein wichtiger Hinweis hierbei ist, dass bei Verwendung eines benutzerdefinierten Layouts mit a Toolbar ActionBar-Implementierung anstelle der Standardimplementierung (z. B. wenn Sie die Kombination DrawerLayout- NavigationView- verwenden Toolbar, um den Schubladeneffekt im Materialstil zu erzielen, der unter der durchscheinenden Statusleiste sichtbar ist) das actionBarThemeAttribut offensichtlich nicht ist Wird automatisch abgeholt (da dies AppCompatActivitystandardmäßig von der erledigt werden soll ActionBar). ToolbarVergessen Sie also nicht, Ihr Thema für Ihre Benutzerdefinition manuell anzuwenden:

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

- Dadurch wird entweder die Standardeinstellung von AppCompat erreicht ThemeOverlay.AppCompat.ActionBar oder in Ihre Überschreibung aufgelöst, wenn Sie das Attribut in Ihrem abgeleiteten .

PS ein kleiner Kommentar über die drawerArrowStyleÜberschreibung und das spinBarsAttribut - was viele Quellen vorschlagen, sollte eingestellt werden true, um die Schubladen- / Pfeilanimation zu erhalten. Das Ding ist, spinBarses ist true standardmäßig in AppCompat (check out dieBase.Widget.AppCompat.DrawerArrowToggle.Common Stil), Sie müssen nicht außer Kraft setzen actionBarThemeüberhaupt die Animation zum Laufen zu bringen. Sie erhalten die Animation auch dann, wenn Sie sie überschreiben und auf das Attribut setzen false. Es handelt sich lediglich um eine andere, weniger zwielichtige Animation. Das Wichtigste hier ist zu verwenden ActionBarDrawerToggle, es ist das, was in der ausgefallenen animierten Zeichnung zieht.

Ivan Bartsov
quelle
2

Ich möchte den obigen Code ein wenig korrigieren

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

und alle anderen Dinge werden gleich bleiben ...

Für diejenigen, die Probleme beim DrawerlayoutÜberlagern der Symbolleiste haben

android:layout_marginTop="?attr/actionBarSize"Zum Stammlayout des Schubladeninhalts hinzufügen

Nitin Misra
quelle
Wie verwenden Sie, getSupportActionBar()wenn Sie nur verlängern Activity?
Wzieba
Sie können einfach nicht, Sie müssen vonActionBarActivity
Nitin Misra