如何从 Android 应用程序 v721库实现 DrawerArrowToggle

现在 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 style _ 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>

我把它添加到我的样式中,但是没有用

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

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

106815 次浏览

If you are using the Support Library provided DrawerLayout as 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):

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.

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

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

Here is my example and I use the new Toolbar to replace the 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>

You can read the documents on 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".

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

Then the animation can be presented.

Hope this can help you.

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 Drawerlayout overlaying toolbar

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

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

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

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

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 drawerArrowStyle in your theme like so:

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

Theme the ActionBar/Toolbar

Override the android:actionBarTheme (actionBarTheme for 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:

<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 Toolbar instead of stock ActionBar implementation (e.g. if you're using the DrawerLayout-NavigationView-Toolbar combo to achieve the Material-style drawer effect where it's visible under translucent statusbar), the actionBarTheme attribute is obviosly not picked up automatically (because it's meant to be taken care of by the AppCompatActivity for the default ActionBar), so for your custom Toolbar don't forget to apply your theme manually:

<!--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.ActionBar or your override if you set the attribute in your derived theme.

PS a little comment about the drawerArrowStyle override and the spinBars attribute -- which a lot of sources suggest should be set to true to get the drawer/arrow animation. Thing is, spinBars it is true by default in AppCompat (check out the Base.Widget.AppCompat.DrawerArrowToggle.Common style), you don't have to override actionBarTheme at 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.