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

然后我调用mDrawerToggle.syncState();我的 onPostCreate()

我尝试搜索如何以编程方式将工具栏图标触发到后退箭头,但没有任何效果。从我收集到的,呼唤

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

从我的片段应该改变图标,但事实并非如此。这可能是一个愚蠢的问题,但我做错了什么?

4

4 回答 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);
            }
        }
    }

Burger 和 Arrow 之间的变形取决于 和 之间的值0f1.0f基本上这些是抽屉传递给 ActionBarDrawerToggle 的值。

我曾经ValueAnimator为这个范围内的值设置动画,即模仿抽屉切换。

null参数是安全的,因为ActionBarDrawerToggle根本不关心抽屉视图。确保你看看新的插值器来完全按照材料设计指南的书来制作动画:

fast_out_linear_in  
fast_out_slow_in

另一种方法是通过反射和调用方法访问mSlider私有字段以在 Burger 和 Arrow 之间切换。 属于 (extends) 类型。ActionBarDrawersetPosition(float position)mSliderDrawerArrowDrawable

就个人而言,我总是尽量避免反思,只要没有其他方法可以做你的肮脏工作。

于 2014-11-10T03:31:31.617 回答
3

随着支持库更新到 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());
于 2015-08-29T00:43:35.490 回答
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);
            }
        }

    });

后 ...

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            getSupportFragmentManager().popBackStack();
            return true;
     ....
 }
于 2015-06-03T19:27:54.543 回答
1

在我的例子中,图标是动画的:我使用了 ActionBarDrawerToggle v7。

主要活动:

    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();
}
于 2014-11-11T12:04:00.500 回答