Панель инструментов AppCompat v7 Up/Back Arrow не работает
У меня есть два фрагмента в активности. Когда отображается фрагмент A, я хочу, чтобы значок гамбургера навигационного ящика показывался, и ящик навигации работал. Когда фрагмент B показывает, я хочу, чтобы стрелка назад показывалась, и когда она щелкнула, сделайте навигацию вверх. Тем не менее, я не могу заставить новую панель инструментов AppCompat v7 показывать стрелку вверх вообще в моей ActionBarActivity, если ядро nav открыто.
В моей работе для моего метода 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);
из моего фрагмента следует изменить значок, но это не так. Это может быть глупый вопрос, но что я делаю неправильно?
Ответы
Ответ 1
Из того, что я видел в исходном коде 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
.
Лично я всегда стараюсь избегать размышлений, пока нет другого способа сделать вашу грязную работу.
Ответ 2
В качестве поддержки библиотеки, обновленной до 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());
Ответ 3
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;
....
}
Ответ 4
В моем случае значок оживляет:
Я использовал 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();
}