7

У меня есть два фрагмента в действии. Когда отображается фрагмент A, я хочу, чтобы значок гамбургера навигационного ящика показывался, и ящик навигации работал. Когда фрагмент B показывает, я хочу, чтобы стрелка назад показывалась, и когда она нажата, выполните навигацию вверх. Однако я не могу заставить новую панель инструментов AppCompat v7 показывать стрелку вверх вообще в моей ActionBarActivity, если ядро ​​nav открыто.AppCompat v7 Панель инструментов Вверх/назад Стрелка не работает

В моей деятельности, для моего 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()

Я попытался найти о том, как Programatically триггером значок панели инструментов на стрелку назад, но ничего не сработало. Из того, что я собрал, позвоните по телефону

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

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

ответ

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

морфинг между Бюргера и Стрелка зависит от значений между 0f и 1.0f, в основном это те значения, что ящик переходит к ActionBarDrawerToggle.

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

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

fast_out_linear_in 
fast_out_slow_in 

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

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

+1

Это именно то, что я искал. Благодаря! –

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(); 
} 
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; 
    .... 
} 
3

В библиотеке поддержки обновлена ​​до 23.0.0, есть лучший способ играть в ящик со стрелкой анимации. Поэтому я собираюсь улучшить ответ Николы.Вот код:

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

 Смежные вопросы

  • Нет связанных вопросов^_^