Панель инструментов AppCompat v7 Стрелка вверх/назад не работает

У меня есть два фрагмента в действии. Когда отображается фрагмент 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);

из моего фрагмента должна измениться иконка, но это не так. Может глупый вопрос, но что я делаю не так?


person Leonardo Casale    schedule 10.11.2014    source источник


Ответы (4)


Из того, что я видел в исходном коде 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 зависит от значений между 0f и 1.0f, в основном это значения, которые ящик передает в ActionBarDrawerToggle.

Я использовал ValueAnimator для анимации значений в этом диапазоне, то есть имитируя переключение ящика.

Аргументы null безопасны, потому что ActionBarDrawerToggle совершенно не заботятся о представлениях ящиков. Не забудьте взглянуть на новые интерполяторы, чтобы сделать анимацию полностью в соответствии с рекомендациями по дизайну материалов:

fast_out_linear_in  
fast_out_slow_in

Другой подход заключается в доступе к mSlider приватному полю ActionBarDrawer через отражение и вызове метода setPosition(float position) для переключения между Burger и Arrow. mSlider имеет тип (расширяется) DrawerArrowDrawable.

Лично я всегда стараюсь избегать размышлений, пока нет другого способа сделать свою грязную работу.

person Nikola Despotoski    schedule 10.11.2014
comment
Это именно то, что я искал. Спасибо! - person Leonardo Casale; 16.11.2014

Поскольку библиотека поддержки обновлена ​​до версии 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());
person ywwynm    schedule 29.08.2015

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;
     ....
 }
person vrbsm    schedule 03.06.2015

В моем случае значок анимирован: я использовал 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();
}
person kunal.c    schedule 11.11.2014