AppCompat v7工具栏的向上/返回箭头无法正常工作

7

在一个活动中我有两个片段。 当片段A显示时,我希望导航抽屉汉堡图标显示并且导航抽屉正常工作。 当片段B显示时,我希望返回箭头显示,并且在点击后进行上导航。 但是,除非导航抽屉打开,否则我似乎无法使新的AppCompat v7工具栏在我的ActionBarActivity内显示向上箭头。

在我的活动中,对于我的onCreate()方法,我有...

toolbar = (Toolbar) findViewById(R.id.toolbar);
if (toolbar != null) {
    setSupportActionBar(toolbar);
}
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);

然后我在我的onPostCreate()函数中调用mDrawerToggle.syncState();

我尝试搜索如何以编程方式触发工具栏图标的后退箭头,但没有任何效果。据我所了解,调用

getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);

我希望从我的片段中更改图标,但实际情况并非如此。这可能是一个愚蠢的问题,但我做错了什么?

4个回答

10

根据我在v7的源代码中观察到的ActionBarDrawerToggle,您可以将图标动画到不同状态,而无需打开抽屉。

 private enum ActionDrawableState{
        BURGER, ARROW
    }
    private static void toggleActionBarIcon(ActionDrawableState state, final ActionBarDrawerToggle toggle, boolean animate){
        if(animate) {
            float start = state == ActionDrawableState.BURGER ? 0f : 1.0f;
            float end = Math.abs(start - 1);
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                ValueAnimator offsetAnimator = ValueAnimator.ofFloat(start, end);
                offsetAnimator.setDuration(300);
                offsetAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
                offsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        float offset = (Float) animation.getAnimatedValue();
                        toggle.onDrawerSlide(null, offset);
                    }
                });
               offsetAnimator.start();
            }else{
                //do the same with nine-old-androids lib :)
            }
        }else{
            if(state == ActionDrawableState.BURGER){
                toggle.onDrawerClosed(null);
            }else{
                toggle.onDrawerOpened(null);
            }
        }
    }

在汉堡图标和箭头图标之间进行形态变换取决于0f1.0f之间的值,这些值基本上是抽屉传递给ActionBarDrawerToggle的值。

我使用了ValueAnimator来动画化这个范围内的值,即模拟抽屉切换。

null参数是安全的,因为ActionBarDrawerToggle根本不关心抽屉视图。确保你查看新的插值器以完全按照材料设计准则进行动画处理:

fast_out_linear_in  
fast_out_slow_in

另一种方法是通过反射访问ActionBarDrawermSlider私有字段,并调用setPosition(float position)方法在汉堡和箭头之间进行切换。 mSlider的类型为(扩展)DrawerArrowDrawable

个人而言,只有在没有其他方法可以完成工作的情况下,我才会尝试使用反射。


1
这正是我正在寻找的。谢谢! - Leonardo Casale

3

随着Support Library更新到23.0.0版本,有一种更好的方式来播放抽屉菜单箭头动画。因此,我将改进@Nikola的答案。以下是代码:

public static void playDrawerToggleAnim(final DrawerArrowDrawable d) {
    float start = d.getProgress();
    float end = Math.abs(start - 1);
    ValueAnimator offsetAnimator = ValueAnimator.ofFloat(start, end);
    offsetAnimator.setDuration(300);
    offsetAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
    offsetAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float offset = (Float) animation.getAnimatedValue();
            d.setProgress(offset);
        }
    });
    offsetAnimator.start();
}

并且你可以随时通过以下方式调用:

playDrawerToggleAnim((DrawerArrowDrawable) toolbar.getNavigationIcon());

2
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            int stackHeight = getSupportFragmentManager().getBackStackEntryCount();
            if (stackHeight > 0) { // if we have something on the stack (doesn't include the current shown fragment)
                getSupportActionBar().setHomeButtonEnabled(true);
                getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            } else {
                getSupportActionBar().setDisplayHomeAsUpEnabled(false);
                getSupportActionBar().setHomeButtonEnabled(false);
            }
        }

    });

After ...

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            getSupportFragmentManager().popBackStack();
            return true;
     ....
 }

1
在我的情况下,图标正在进行动画: 我使用了ActionBarDrawerToggle v7。
MainActivity:
    Toolbar toolbar = (Toolbar) findViewById(R.id.tool1);

    setSupportActionBar(toolbar);
    toolbar.setTitle("ToolBar Demo");
    toolbar.setLogo(R.drawable.ic_launcher);

    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);

    mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar,
            R.string.open_navigation_drawer,
            R.string.close_navigation_drawer) {

        @Override
        public void onDrawerSlide(View drawerView, float slideOffset) {
            // TODO Auto-generated method stub
            super.onDrawerSlide(drawerView, slideOffset);
        }

        /** Called when a drawer has settled in a completely closed state. */
        @Override
        public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);
            getSupportActionBar().setTitle("hello");
        }

        /** Called when a drawer has settled in a completely open state. */
        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            getSupportActionBar().setTitle("hi");
        }
    };
    mDrawerLayout.setDrawerListener(mDrawerToggle);



}

@Override
public boolean onOptionsItemSelected(MenuItem item) { // <---- added
    if (mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
protected void onPostCreate(Bundle savedInstanceState) { // <---- added
    super.onPostCreate(savedInstanceState);
    mDrawerToggle.syncState(); // important statetment for drawer to
                                // identify
                                // its state
}

@Override
public void onConfigurationChanged(Configuration newConfig) { // <---- added
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
}

@Override
public void onBackPressed() {
    if (mDrawerLayout.isDrawerOpen(Gravity.START | Gravity.LEFT)) { // <----
                                                                    // added
        mDrawerLayout.closeDrawers();
        return;
    }
    super.onBackPressed();
}

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