Android 5.0 - 将AppCompat v7 21主页图标从汉堡菜单动画变为返回箭头的程序实现

6
我目前正在将一个以Fragment为导向的应用程序(我有一个Activity,其中包含一个FrameLayout容器,作为所有Fragment的宿主)更新到Material Design。当替换Fragment时,我想要将汉堡图标动画化为后退箭头。
基本上,如果这还不够清楚,我想实现的是在这里。我不想使用该库(MaterialMenu),我想尽可能地使用官方的AppCompat库。
我通过这个解决方案实现了这个效果,但我无法弄清如何在替换Fragment时使ActionBarDrawerToggle作为返回按钮。所以我的问题是:一旦Fragement被替换,后退箭头图标是否仍然应该是ActionBarDrawerToggle?在这种情况下,如何覆盖它,使其像onBackPressed()一样工作而不是打开抽屉?我已经尝试过这个方法,但它不起作用:
 @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        switch (item.getItemId())
        {
            case android.R.id.home:
                getActivity().onBackPressed();
                return true;
         }
         return false;
    }

提前致谢。

3个回答

7

我认为,在侧拉菜单开关中跟踪用户是否手动打开更加清晰。这是我最终的做法:

public class ManualActionBarDrawerToggle extends ActionBarDrawerToggle {
    private static final float MENU_POSITION = 0f;
    private static final float ARROW_POSITION = 1.0f;

    private final int animationLength;
    private final DrawerLayout drawerLayout;
    private final Activity activity;
    private State currentState;

    private enum State { UP_ARROW, MENU }

    public ManualActionBarDrawerToggle(Activity activity, DrawerLayout drawerLayout, int openDrawerContentDescriptionResource, int closeDrawerContentDescriptionResource) {
        super(activity, drawerLayout, openDrawerContentDescriptionResource, closeDrawerContentDescriptionResource);
        animationLength = activity.getResources().getInteger(android.R.integer.config_shortAnimTime);
        this.drawerLayout = drawerLayout;
        this.activity = activity;
        currentState = State.MENU;
    }

    public void animateToBackArrow() {
        ValueAnimator anim = ValueAnimator.ofFloat(MENU_POSITION, ARROW_POSITION);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            float slideOffset = (Float) valueAnimator.getAnimatedValue();
            onDrawerSlide(drawerLayout, slideOffset);
            }
        });

        anim.setInterpolator(new DecelerateInterpolator());
        anim.setDuration(animationLength);
        anim.start();

        currentState = State.UP_ARROW;
    }

    public void animateToMenu() {
        ValueAnimator anim = ValueAnimator.ofFloat(ARROW_POSITION, MENU_POSITION);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float slideOffset = (Float) valueAnimator.getAnimatedValue();
                onDrawerSlide(drawerLayout, slideOffset);
            }
        });

        anim.setInterpolator(new DecelerateInterpolator());
        anim.setDuration(animationLength);
        anim.start();

        currentState = State.MENU;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case (android.R.id.home):
                if (currentState == State.UP_ARROW) {
                    activity.onBackPressed();
                    return true;
                }
        }
        return super.onOptionsItemSelected(item);
    }
}

在初始化任何内容之前,不要忘记调用activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true)。 - Udi Oshi

1

这个库的菜单可绘制对象有一个可以动画状态的方法:

如果你想从 Burger 切换到 Arrow,你可以调用以下方法:

mMaterialMenu.animateState(IconState.ARROW);

确实,正如我所说的,我已经使用过它,但在我看来,它的外观不如默认图标好看 :)。 - MathieuMaree
那么,为什么不切换到v7 ActionBarDrawerToggle呢? - Nikola Despotoski
好的,我做了...?我想要的不是在打开/关闭抽屉时切换动画;而是在切换片段时使用相同的动画。并且一旦添加了片段,我希望切换按钮像主页/返回箭头一样起作用。 - MathieuMaree
请使用此链接 http://developer.android.com/training/implementing-navigation/ancestral.html。 - xDragonZ
我们如何在xml中将默认菜单Drawable保持为“X”状态。我正在使用在活动中mMaterialMenu.animateState(IconState.X);从默认的“汉堡包”菜单切换到“X”菜单。但它会带有动画效果进行更改。我没有找到任何可以在xml中更改状态的属性。请帮忙。 - Dory
我找到了解决方法,不再使用 mMaterialMenu.animateState(IconState.X); 而是使用 mMaterialMenu.setState(IconState.X);。通过这种方式,我能够将状态从默认的 BURGER 更改为 X,虽然我没有在 xml 中找到任何要设置的属性。 - Dory

1

好的,我找到了一种方法。我相当确定这不是一个好的解决方案,因为我正在使用 ActionBarDrawerToggle 来完成与其创建目的不同的任务。

但是它有效,所以这就是我所做的。我只是创建了一个自定义的 ActionBarDrawerToggle,其中我重写了 onOptionsItemSelected(...) 方法:

class MyDrawerToggle extends ActionBarDrawerToggle
{
    // ... Default constructors matching super go here

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
        // If the back stack isn't empty, ie if I'm not in a Fragment 
        // accessible from the NavigationDrawer, I simulate the onBackPressed behaviour
        if (getFragmentManager().getBackStackEntryCount() != 0)
        {
            onBackPressed();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

如果有更好的解决方案,请随时提出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接