Как реализовать 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. Однако я не могу его стилизовать. Пожалуйста помоги

Я нашел его стиль в файле style_base.xml v7.

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

Но вылетает и при этом сообщает об ошибке цветотипа. Что мне не хватает?

Bignadad
источник

Ответы:

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 Должны

ли полосы вращаться или нет во время перехода.
Должно быть логическое значение, либо «истина», либо «ложь».

Итак, вы установили это: <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. кто-нибудь знает, почему это произошло?
pez
1
Я использовал setSupportActionBar(mToolbar);и тоже определил, <item name="spinBars">true</item>но анимация не работает
SweetWisher ツ
2
Следует использовать ActionBarDrawerToggle (Activity, DrawerLayout, int, int), если вы устанавливаете панель инструментов в качестве ActionBar вашей активности.
Питер Чжао,
24

Если вы используете библиотеку поддержки, предоставленную DrawerLayout, как предложено в разделе « Создание панели навигации» , вы можете использовать недавно добавленный android.support. v7 .app.ActionBarDrawerToggle (примечание: отличается от устаревшего android.support. v4 .app.ActionBarDrawerToggle ):

показывает значок гамбургера, когда ящик закрыт, и стрелку, когда ящик открыт. Он анимирует эти два состояния при открытии ящика.

Хотя обучение не было обновлено с учетом устаревшего / нового класса, вы должны иметь возможность использовать его почти точно такой же код - единственная разница в его реализации - это конструктор.

ianhanniballake
источник
Я использую v4 в своем приложении bc, мне не нужно поддерживать устройства до api 15. Итак, если бы я хотел, чтобы это работало, мне пришлось бы использовать переключатель ящика панели действий v7? Если бы я сделал это, мне бы не пришлось преобразовывать все свои стили в AppCompat и фрагментировать действия в действия на панели действий и так далее? Или я могу реализовать только переключатель ящика из v7. Сейчас я использую v7 для просмотра карточек. Должен ли я вообще использовать v4, если я не поддерживаю api ниже 15? И, наверное, мне нужна версия 7 для просмотра карт.
Bignadad
Вся совместимость библиотеки поддержки для дизайна материалов реализована в v7-appcompat и рекомендуется, если вы хотите поддерживать этот стиль на устройствах <5.0. AppCompat построен на основе v4 и требует наличия v4, так что действительно важно, хотите ли вы вообще использовать AppCompat. Если вы уже используете FragmentActivity, вы уже довольно близки - разница в стилях сейчас довольно мала (в основном просто заменяется атрибуты android: на атрибуты без пространства имен).
ianhanniballake
Обновил вопрос, если вы не против взглянуть, пожалуйста
Бигнадад
Это действительно отдельный вопрос по стилю. Я бы предложил отправить эту часть как целый другой вопрос (не стесняйтесь добавлять комментарий со ссылкой на него).
ianhanniballake
1
@mraviator - да: измените XML, затем создайте и прикрепите файл v7 ActionBarDrawerToggle. В каноническом ответе создателя AppCompat есть полный пример того, как должен быть структурирован ваш XML.
ianhanniballake
17

Я создал небольшое приложение с похожей функциональностью

Основное занятие

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>

Мои стили в 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>
Тим
источник
1
Это отлично работает, но я не хочу использовать Title, как мне с этим справиться? Потому что, если я использую Theme.AppCompat.Light.NoActionBar , он определенно даст мне NULL в getSupportActionBar
SweetWisher ツ
Я использовал приведенный выше код. У меня есть исключение: у этого действия уже есть панель действий, предоставленная декором окна в строке setsupportactionbar (панель инструментов). Я использовал getSupportActionBar (). Hide (); Перед 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
Nitin Misra