7
Arbeiten

Ich habe zwei Fragmente in einer Aktivität. Wenn Fragment A zeigt, möchte ich die Navigationsleiste Burger Symbol zu zeigen und die Navigationsleiste zu arbeiten. Wenn Fragment B angezeigt wird, möchte ich den Pfeil zurück zu zeigen, und wenn es angeklickt wird eine Navigation aufmöbeln. Ich kann jedoch nicht scheinen, dass die neue AppCompat v7-Symbolleiste den Pfeil nach oben in meiner ActionBarActivity nur dann anzeigt, wenn das Nav-Fach geöffnet ist.AppCompat v7 Toolbar Up/Zurück Pfeil Nicht

In meiner Tätigkeit für meine onCreate() -Methode Ich habe ...

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

Und ich rufe dann mDrawerToggle.syncState(); in meinem onPostCreate()

Ich habe versucht, die Suche, wie man programmatisch Trigger das Symbol in der Symbolleiste auf den Zurück-Pfeil, aber nichts hat funktioniert. Von dem, was ich gesammelt habe,

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

von meinem Fragmente Aufruf sollte das Symbol ändern, aber das ist nicht der Fall. Das mag eine dumme Frage sein, aber was mache ich falsch?

Antwort

10

Von dem, was ich im Quellcode von v7 ActionBarDrawerToggle gesehen habe, können Sie das Symbol zu verschiedenen Zuständen animieren, ohne die Schublade geöffnet zu haben.

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

Morphing zwischen Burger und Pfeil zwischen 0f und 1.0f auf Werten abhängt, grundsätzlich sind diese Werte, die die Schublade in die ActionBarDrawerToggle gibt.

Ich habe ValueAnimator verwendet, um Werte in diesem Bereich zu animieren, d. H. Die Schublade toggeln.

null Argumente sind sicher, denn ActionBarDrawerToggle kümmert sich überhaupt nicht um Schublade Ansichten. Achten Sie darauf, einen Blick auf neue Interpolatoren nehmen die Animation voll-by-the-Book von Material Design-Richtlinien zu tun:

fast_out_linear_in 
fast_out_slow_in 

Ein weiterer Ansatz ist mSlider privaten Bereich des ActionBarDrawer durch Reflexion zuzugreifen und setPosition(float position) Methode aufrufen um zwischen Burger und Arrow zu wechseln. mSlider ist vom Typ (erweitert) DrawerArrowDrawable.

Ich persönlich versuche immer, Reflektionen zu vermeiden, solange es keine andere Möglichkeit gibt, Ihre schmutzige Arbeit zu erledigen.

+1

Das ist genau das, was ich suchte. Vielen Dank! –

1

In meinem Fall animiert das Symbol: Ich habe ActionBarDrawerToggle v7 verwendet.

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

    }); 

Nach ...

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

Als Bibliothek Unterstützung 23.0.0 aktualisiert, gibt es eine bessere Art und Weise schubladen Pfeil Animation zu spielen. Also werde ich @ Nikolas Antwort verbessern.Hier Code:

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

Und es nennen, wann immer Sie wollen von:

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