Як реалізувати DrawerArrowToggle з бібліотеки Android appcompat v7 21


97

Отож, коли Android 5.0 вийшов, мені було цікаво, як реалізувати анімовані піктограми панелі дій.

Ця бібліотека тут реалізує це добре для мене, але оскільки в бібліотеці appcompat v7 є, як це можна реалізувати?

Бібліотека посилається на це в themes.xml

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

Під цей стиль

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

ОНОВЛЕННЯ

Я реалізував це за допомогою v7 DrawerToggle. Однак я не можу це зробити. Будь ласка, допоможіть

Я знайшов стиль для нього в 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>

Я додав це до своїх стилів і не працював. Також додано в мій 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>

Але виходить з ладу і повідомляє про помилку типу кольорів при цьому. Що я пропускаю?

Відповіді:


243

По-перше, ви повинні знати, що android.support.v4.app.ActionBarDrawerToggleце застаріле.

Ви повинні замінити це на android.support.v7.app.ActionBarDrawerToggle.

Ось мій приклад, і я використовую новий Toolbarдля заміни 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>

Ви можете читати документи на AndroidDocument # DrawerArrowToggle_spinBars

Цей атрибут є ключем для реалізації анімації меню до стрілки.

public static int DrawerArrowToggle_spinBars

Чи повинні бари обертатися під час переходу чи ні,
Має бути булевим значенням, або "true", або "false".

Отже, ви встановили це: <item name="spinBars">true</item>.

Тоді анімацію можна представити.

Сподіваюся, що це може вам допомогти.


12
У мене виникли проблеми з тим, щоб з'явитись значок гамбургера. виклик mDrawerToggle.syncState();виправлено.
aheuermann

1
для мене getSupportActionBar () повертає null .. що може бути причиною?
Ramesh_D

2
Зазначає Android Studio Cannot resolve method setSupportActionBar(android.widget.Toolbar). Я також пробував android.support.v7.toolbar. Хтось знає, чому це відбувається?
пез

1
Я використовував setSupportActionBar(mToolbar);і також визначав, <item name="spinBars">true</item>але анімація не працює
SweetWisher

2
Слід використовувати ActionBarDrawerToggle (Activity, DrawerLayout, int, int), якщо ви встановлюєте панель інструментів як панель дій для вашої діяльності.
Пітер Чжао

24

Якщо ви використовуєте Бібліотеку підтримки, надану DrawerLayout, як це запропоновано в навчанні "Створення навігаційного ящика" , ви можете використовувати нещодавно доданий android.support. v7 .app.ActionBarDrawerToggle (примітка: відрізняється від застарілого android.support. v4 .app.ActionBarDrawerToggle ):

показує піктограму Гамбургер, коли ящик закрито, а стрілку - коли ящик відкритий. Він оживляє між цими двома станами, коли ящик відкривається.

Хоча навчання не оновлено для врахування депресації / нового класу, ви повинні мати можливість користуватися ним майже таким самим кодом - єдиною різницею в його реалізації є конструктор.


Я використовую v4 в моїй програмі bc мені не потрібно підтримувати пристрої до api 15. Отже, якщо я хотів, щоб це працювало, я повинен був би використовувати перемикач ящика панелі дій v7? Якби я це зробив, чи не доведеться я перетворювати всі мої стилі в AppCompat та дії з фрагментами в дії на панелі дій тощо? Або я можу реалізувати лише тумблер Drawer від v7. Зараз я використовую v7 для перегляду карт. Чи потрібно мені навіть використовувати v4, якщо я не підтримую api нижче 15? І я думаю, мені потрібен v7 для перегляду карт.
Bignadad

Вся сумісність бібліотеки підтримки для дизайну матеріалів реалізована в v7-appcompat і рекомендується, якщо ви хочете підтримувати цей стиль на пристроях <5.0. AppCompat розроблений і вимагає версії 4, тому це дійсно актуально, якщо ви хочете використовувати AppCompat взагалі. Якщо ви вже використовуєте FragmentActivity, ви вже досить близькі - різниця в стилі зараз досить мала (в основному це лише заміна атрибутів android: атрибутів, що не відрізняються від імен).
ianhanniballake

Оновлено питання, якщо ви не проти заглянути, будь ласка
Bignadad

Це справді зовсім окреме питання щодо стилізації. Я б запропонував надіслати цю частину як зовсім інше питання (сміливо додайте коментар із посиланням на нього).
ianhanniballake

1
@mraviator - так: зміни XML, потім створити та приєднати v7 ActionBarDrawerToggle. Канонічний відповідь від виробника AppCompat має повний приклад того, як повинен бути структурований ваш XML.
ianhanniballake

17

Я створив невеликий додаток, який мав подібну функціональність

MainActivity

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

Мій XML цієї активності

<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

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

Мій стиль теми

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

Мої стилі у значеннях-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
Це ідеально, але я не хочу використовувати Title, тому як я можу це впоратися? Тому що якщо я використовую Theme.AppCompat.Light.NoActionBar , він обов'язково дасть мені NULL в getSupportActionBar
SweetWisher ツ

Я використовував вище код. Я отримав виняток: у цій активності вже є панель дій, що надається декором вікна в рядку setupportaction (панелі інструментів). Я використав getSupportActionBar (). Hid (); Перед setContentView (R.layout.activity_main); Зараз це працює.
Тріумальвалаван

setSupportActionBar (панель інструментів); також прокоментував.
Тріуммалаван

9

Щоб відповісти на оновлену частину Вашого запитання: для стилювання піктограми / стрілки ви можете зробити два варіанти:

Стиліруйте саму стрілку

Для цього drawerArrowStyleперейдіть у свою тему так:

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

Це, мабуть, не те, що ви хочете , тому що сам ActionBar повинен мати послідовну стилізацію зі стрілкою, тому, швидше за все, вам потрібен варіант два:

Тема панелі дій / панелі інструментів

Замініть атрибут android:actionBarTheme( actionBarThemeдля appcompat) глобальної теми програми на власну тему (з якої ви, мабуть, маєте виходити ThemeOverlay.Material.ActionBar/ThemeOverlay.AppCompat.ActionBar) так:

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

Тут важливим є те, що при використанні користувальницького макета Toolbarзамість реалізації ActionBar (наприклад, якщо ви використовуєте комбо DrawerLayout- NavigationView- Toolbarдля досягнення ефекту шухляди у стилі Матеріал там, де його видно на напівпрозорій панелі стану), actionBarThemeатрибут не відповідає підбирається автоматично (оскільки AppCompatActivityза замовчуванням це повинно бути опікуватися ActionBar), тому для вашого звичаю Toolbarне забудьте застосувати свою тему вручну:

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

- це вирішиться як за замовчуванням AppCompat, так ThemeOverlay.AppCompat.ActionBarі для вашого заміщення, якщо ви встановите атрибут у похідній темі.

PS невеликий коментар про drawerArrowStyleпереосмислення та spinBarsатрибут - які багато джерел пропонують встановити, trueщоб отримати анімацію "ящик / стрілка". Річ у тому, spinBarsщо це true за замовчуванням у AppCompat (ознайомтеся зі Base.Widget.AppCompat.DrawerArrowToggle.Commonстилем), вам не доведеться переосмислювати actionBarThemeвзагалі, щоб анімація працювала. Ви отримуєте анімацію, навіть якщо ви її falseзамінюєте і встановлюєте атрибут , це просто інша, менш кручена анімація. Тут важливо використовувати ActionBarDrawerToggle, це те, що тягне в фантазійне анімоване малювання.


2

Я хочу трохи виправити наведений вище код

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

і всі інші речі залишаться такими ж ...

Для тих, хто має проблеми з Drawerlayoutнакладанням панелі інструментів

додати android:layout_marginTop="?attr/actionBarSize"до кореневого макета вмісту ящика


як ти користуєшся, getSupportActionBar()коли просто розширюєшся Activity?
wzieba

просто не можете, ви повинні продовжити зActionBarActivity
Нітін Місра
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.