如何从 Android appcompat v7 21 库实现 DrawerArrowToggle

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26434504/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:25:41  来源:igfitidea点击:

How to implement DrawerArrowToggle from Android appcompat v7 21 library

androidandroid-actionbarandroid-5.0-lollipopandroid-appcompatdrawertoggle

提问by Bignadad

So now that Android 5.0 was released i was wondering how to implement the animated actionbar icons.

所以现在 Android 5.0 发布了,我想知道如何实现动画操作栏图标。

This library hereimplements it fine for me but since the appcompat v7 library has it how can it be implemented?

这里的这个库对我来说很好,但是既然 appcompat v7 库有它,它如何实现?

The library references it in themes.xml

库在 themes.xml 中引用它

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

Under this style

在这种风格下

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

UPDATE

更新

I got this implemented using the v7 DrawerToggle. However I cannot style it. Please Help

我使用 v7 DrawerToggle 实现了这个。但是我不能设计它。请帮忙

I found the styling for it in the v7 styles_base.xml

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

I added this to my styles and did not work. Also added to my attr.xml

我将此添加到我的样式中,但不起作用。也添加到我的 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>

But crashes and says color type error when doing so. What am i missing?

但是这样做时会崩溃并说颜色类型错误。我错过了什么?

回答by Yong

First, you should know now the android.support.v4.app.ActionBarDrawerToggleis deprecated.

首先,您现在应该知道 已android.support.v4.app.ActionBarDrawerToggle弃用。

You must replace that with android.support.v7.app.ActionBarDrawerToggle.

您必须将其替换为android.support.v7.app.ActionBarDrawerToggle.

Here is my example and I use the new Toolbarto replace the ActionBar.

这是我的示例,我使用 newToolbar替换ActionBar.

MainActivity.java

主活动.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>

You can read the documents on AndroidDocument#DrawerArrowToggle_spinBars

您可以阅读AndroidDocument#DrawerArrowToggle_spinBars上的文档

This attribute is the key to implement the menu-to-arrow animation.

该属性是实现菜单到箭头动画的关键。

public static int DrawerArrowToggle_spinBars

Whether bars should rotate or not during transition
Must be a boolean value, either "true" or "false".

public static int DrawerArrowToggle_spinBars

条在过渡期间是否应该旋转
必须是布尔值,“true”或“false”。

So, you set this: <item name="spinBars">true</item>.

所以,你设置这样的:<item name="spinBars">true</item>

Then the animation can be presented.

然后可以呈现动画。

Hope this can help you.

希望这可以帮到你。

回答by ianhanniballake

If you are using the Support Library provided DrawerLayoutas suggested in the Creating a navigation drawer training, you can use the newly added android.support.v7.app.ActionBarDrawerToggle(note: different from the now deprecated android.support.v4.app.ActionBarDrawerToggle):

如果您按照创建导航抽屉培训中的建议使用支持库提供的DrawerLayout,则可以使用新添加的android.support。V7.app.ActionBarDrawerToggle(注:从现在反对的不同。android.support V4.app.ActionBarDrawerToggle):

shows a Hamburger icon when drawer is closed and an arrow when drawer is open. It animates between these two states as the drawer opens.

抽屉关闭时显示汉堡图标,抽屉打开时显示箭头。当抽屉打开时,它会在这两种状态之间进行动画处理。

While the training hasn't been updated to take the deprecation/new class into account, you should be able to use it almost exactly the same code - the only difference in implementing it is the constructor.

虽然培训尚未更新以考虑弃用/新类,但您应该能够使用几乎完全相同的代码 - 实现它的唯一区别是构造函数。

回答by tim

I created a small application which had similar functionality

我创建了一个具有类似功能的小应用程序

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

My XML of that Activity

我的那个活动的 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>

My Custom Toolbar XML

我的自定义工具栏 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>

My Theme Style

我的主题风格

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

My Styles in values-v21

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

回答by Ivan Bartsov

To answer the updated part of your question: to style the drawer icon/arrow, you have two options:

要回答问题的更新部分:要设置抽屉图标/箭头的样式,您有两个选择:

Style the arrow itself

设计箭头本身

To do this, override drawerArrowStylein your theme like so:

为此,请覆盖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>

This is probably not what you want, because the ActionBar itself should have consistent styling with the arrow, so, most probably, you want the option two:

这可能不是您想要的,因为 ActionBar 本身应该具有与箭头一致的样式,因此,很可能您需要选项二:

Theme the ActionBar/Toolbar

主题操作栏/工具栏

Override the android:actionBarTheme(actionBarThemefor appcompat) attribute of the global application theme with your own theme (which you probably should derive from ThemeOverlay.Material.ActionBar/ThemeOverlay.AppCompat.ActionBar) like so:

使用您自己的主题(您可能应该从中派生)覆盖全局应用程序主题的android:actionBarTheme( actionBarThemefor 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>

An important note here is that when using a custom layout with a Toolbarinstead of stock ActionBar implementation (e.g. if you're using the DrawerLayout-NavigationView-Toolbarcombo to achieve the Material-style drawer effect where it's visible under translucent statusbar), the actionBarThemeattribute is obviosly not picked up automatically (because it's meant to be taken care of by the AppCompatActivityfor the default ActionBar), so for your custom Toolbardon't forget to apply your theme manually:

一个重要的注意这里是当使用带有自定义布局Toolbar,而不是股票的动作条的实施(例如,如果您使用的是DrawerLayout- NavigationView-Toolbar组合来实现材料式抽屉效果,即它在半透明的状态栏是可见的),该actionBarTheme属性是obviosly不自动拾取(因为它是由AppCompatActivity默认值处理的ActionBar),因此对于您的自定义,Toolbar请不要忘记手动应用您的主题:

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

-- this will resolve to either AppCompat's default ThemeOverlay.AppCompat.ActionBaror your override if you set the attribute in your derived theme.

--ThemeOverlay.AppCompat.ActionBar如果您在派生主题中设置属性,这将解析为 AppCompat 的默认值或您的覆盖。

PSa little comment about the drawerArrowStyleoverride and the spinBarsattribute -- which a lot of sources suggest should be set to trueto get the drawer/arrow animation. Thing is, spinBarsit is trueby defaultin AppCompat (check out the Base.Widget.AppCompat.DrawerArrowToggle.Commonstyle), you don't have to override actionBarThemeat all to get the animation working. You get the animation even if you do override it and set the attribute to false, it's just a different, less twirly animation. The important thing here is to use ActionBarDrawerToggle, it's what pulls in the fancy animated drawable.

PS关于drawerArrowStyle覆盖和spinBars属性的一些评论- 许多来源建议应该设置true为获取抽屉/箭头动画。spinBars事实是,它true默认在 AppCompat 中(查看Base.Widget.AppCompat.DrawerArrowToggle.Common样式),您根本不必覆盖actionBarTheme即可使动画正常工作。即使您确实覆盖了动画并将属性设置为false,您也会获得动画,这只是一个不同的、不那么扭曲的动画。这里重要的是使用ActionBarDrawerToggle,它是吸引精美动画可绘制对象的原因。

回答by Nitin Misra

I want to correct little bit the above code

我想更正一下上面的代码

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

and all the other things will remain same...

所有其他的事情都将保持不变......

For those who are having problem Drawerlayoutoverlaying toolbar

对于那些在Drawerlayout覆盖工具栏时遇到问题的人

add android:layout_marginTop="?attr/actionBarSize"to root layout of drawer content

添加android:layout_marginTop="?attr/actionBarSize"到抽屉内容的根布局