7

Tôi có hai đoạn trong một hoạt động. Khi đoạn A hiển thị, tôi muốn biểu tượng bánh burger ngăn kéo điều hướng hiển thị và ngăn điều hướng hoạt động. Khi đoạn B đang hiển thị, tôi muốn mũi tên quay lại hiển thị và khi được nhấp vào làm điều hướng lên. Tuy nhiên, tôi không thể có được thanh công cụ AppCompat v7 mới để hiển thị mũi tên lên ở tất cả bên trong ActionBarActivity của tôi trừ khi ngăn điều hướng mở.AppCompat v7 Thanh công cụ Lên/Mũi tên quay lại Không hoạt động

Trong hoạt động của tôi, đối với phương pháp tôi có onCreate của tôi() ...

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

Và sau đó tôi gọi mDrawerToggle.syncState(); trong onPostCreate của tôi()

Tôi đã thử tìm kiếm trên làm thế nào để kích hoạt programatically biểu tượng thanh công cụ ở mũi tên quay lại nhưng không có gì hoạt động. Từ những gì tôi đã thu thập, hãy gọi

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

từ đoạn của tôi sẽ thay đổi biểu tượng nhưng không phải như vậy. Đây có thể là một câu hỏi ngu ngốc, nhưng tôi đang làm gì sai?

Trả lời

10

Từ những gì tôi đã thấy trong mã nguồn của v7 ActionBarDrawerToggle, bạn có thể tạo biểu tượng động cho các trạng thái khác nhau mà không cần mở ngăn chứa.

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 giữa Burger và mũi tên phụ thuộc vào giá trị giữa 0f1.0f, về cơ bản đây là những giá trị mà ngăn kéo đi để ActionBarDrawerToggle.

Tôi đã sử dụng ValueAnimator để tạo hiệu ứng giá trị trong phạm vi này, tức là bắt chước ngăn bật.

null đối số an toàn vì ActionBarDrawerToggle không quan tâm gì cả về chế độ xem ngăn. Hãy chắc chắn rằng bạn có một cái nhìn tại interpolators mới để làm hình ảnh động đầy đủ-by-the-book của hướng dẫn thiết kế vật liệu:

fast_out_linear_in 
fast_out_slow_in 

Một cách khác là để truy cập mSlider lĩnh vực tư nhân của ActionBarDrawer qua phản ánh và gọi setPosition(float position) phương pháp để chuyển đổi giữa Burger và Arrow. mSlider thuộc loại (mở rộng) DrawerArrowDrawable.

Cá nhân, tôi luôn cố gắng tránh sự phản chiếu, miễn là không có cách nào khác để thực hiện công việc bẩn thỉu của bạn.

+1

Đây chính là điều tôi đang tìm kiếm. Cảm ơn! –

1

Trong trường hợp của tôi, biểu tượng hoạt ảnh: Tôi đã sử dụng 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); 
      } 
     } 

    }); 

Sau ...

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

Như Thư viện hỗ trợ cập nhật để 23.0.0, có một cách tốt hơn để chơi ngăn kéo mũi tên hình ảnh động. Vì vậy, tôi sẽ cải thiện câu trả lời của @ Nikola.Dưới đây là 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(); 
} 

Và gọi nó là bất cứ khi nào bạn muốn bằng cách:

playDrawerToggleAnim((DrawerArrowDrawable) toolbar.getNavigationIcon()); 
Các vấn đề liên quan