我已经实现了主/细节流,我想在添加 fragment 后获得从汉堡包图标到箭头图标的过渡动画(与打开抽屉导航时的动画相同)。

我正在使用如下代码:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    toggle = new ActionBarDrawerToggle(this, drawer, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.setDrawerIndicatorEnabled(true);
    toggle.syncState();

    //Add home page fragment
    FragmentManager fragmentManager = getFragmentManager();
    HabitHomeFragment homePageFragment = new HabitHomeFragment();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    fragmentTransaction.replace(R.id.habit_home, homePageFragment);
    fragmentTransaction.commit();}

在添加细节 fragment 时:
public void showDetails() {
        toggle.setDrawerIndicatorEnabled(false);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        fragmentTransaction.replace(R.id.habit_home, habitDetailsFragment).addToBackStack("detail").commit();}

和工具栏:
<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>
....

目前在更改 fragment 后,图标只是更改,没有动画。

最佳答案

先做一些解释。

  • android.support.v7.app.ActionBarDrawerToggle 使用特殊的 drawable 类来制作汉堡到箭头的图标和动画。
  • 类是 android.support.v7.graphics.drawable.DrawerArrowDrawable
  • DrawerArrowDrawable 使用 setProgress(float progress) 方法实现动画,其中进度从 0(汉堡包)到 1(箭头)。
  • ActionBarDrawerToggle 使用调用 private void setPosition(float position)
  • DrawerArrowDrawable.setProgress()
  • ActionBarDrawerToggle 使用public void onDrawerSlide(View drawerView, float slideOffset) 调用私有(private)setPosition()
  • ActionBarDrawerToggle 在构造函数中调用 toolbar.setNavigationOnClickListener() 及其监听器,用于切换抽屉。
  • ActionBarDrawerToggle 跟踪实际的 DrawerArrowDrawable 状态。 ToolbarActionBar 不跟踪实际的 DrawerArrowDrawable 状态。

  • 那么,你应该在 Activity 中做什么。选项-A,使用 ActionBarDrawerToggle。
        // define a variable to track hamburger-arrow state
        protected boolean isHomeAsUp = false;
    
        protected DrawerLayout drawer;
        protected Toolbar toolbar;
        protected ActionBarDrawerToggle toggle;
    
        // I've implemented it in setContentView(), but you can implement it in onCreate()
        @Override
        public void setContentView(@LayoutRes int layoutResID) {
            super.setContentView(layoutResID);
    
            toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
    
            drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
            toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
            drawer.addDrawerListener(toggle);
            toggle.syncState();
    
            // overwrite Navigation OnClickListener that is set by ActionBarDrawerToggle
            toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (drawer.isDrawerOpen(GravityCompat.START)){
                        drawer.closeDrawer(GravityCompat.START);
                    } else if (isHomeAsUp){
                        onBackPressed();
                    } else {
                        drawer.openDrawer(GravityCompat.START);
                    }
                }
            });
        }
    
        // call this method for animation between hamburged and arrow
        protected void setHomeAsUp(boolean isHomeAsUp){
            if (this.isHomeAsUp != isHomeAsUp) {
                this.isHomeAsUp = isHomeAsUp;
    
                ValueAnimator anim = isHomeAsUp ? ValueAnimator.ofFloat(0, 1) : ValueAnimator.ofFloat(1, 0);
                anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator valueAnimator) {
                        float slideOffset = (Float) valueAnimator.getAnimatedValue();
                        toggle.onDrawerSlide(drawer, slideOffset);
                    }
                });
                anim.setInterpolator(new DecelerateInterpolator());
                // You can change this duration to more closely match that of the default animation.
                anim.setDuration(400);
                anim.start();
            }
        }
    

    或者,您可以使用 DrawerArrowDrawabletoolbar.setNavigationIcon() 设置为导航图标,并在没有 ActionBarDrawerToggle 的情况下对其进行动画处理
    见选项-B:https://stackoverflow.com/a/42024138/1148784

    10-08 07:08