【问题标题】:Transition animation from hamburger to arrow icon on adding fragment添加片段时从汉堡包到箭头图标的过渡动画
【发布时间】:2016-07-12 17:14:49
【问题描述】:

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

我正在使用如下代码:

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

在添加细节片段时:

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> 
....    

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

【问题讨论】:

  • 你找到解决方案了吗?
  • 我还没有找到任何解决这个问题的方法。
  • @Questioner,我找到了两个解决方案。查看答案。

标签: android android-fragments animation


【解决方案1】:

先解释一下。

  1. android.support.v7.app.ActionBarDrawerToggle 使用特殊的可绘制类来处理汉堡到箭头的图标和动画。

  2. 班级是android.support.v7.graphics.drawable.DrawerArrowDrawable

  3. DrawerArrowDrawable 使用方法setProgress(float progress) 实现动画,其中进度是从0(汉堡包)到1(箭头)。

  4. ActionBarDrawerToggle 使用调用DrawerArrowDrawable.setProgress()private void setPosition(float position)

  5. ActionBarDrawerToggle 使用public void onDrawerSlide(View drawerView, float slideOffset) 调用私有setPosition()

  6. ActionBarDrawerToggle 在构造函数中调用toolbar.setNavigationOnClickListener() 及其监听器,用于切换抽屉。

  7. ActionBarDrawerToggle 跟踪实际的DrawerArrowDrawable 状态。 ToolbarActionBar 不跟踪实际的 DrawerArrowDrawable 状态。

那么,你应该在活动中做什么。 Option-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();
        }
    }

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

【讨论】:

    【解决方案2】:

    请参阅我的另一个答案以获取解释https://stackoverflow.com/a/42023946/1148784。这是选项-B。 Activity 类的代码。我们在这里不使用ActionBarDrawerToggle

        protected boolean isHomeAsUp = false;
        DrawerArrowDrawable homeDrawable;
        protected Toolbar toolbar;
        protected DrawerLayout drawer;
    
        @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);
    
            homeDrawable = new DrawerArrowDrawable(toolbar.getContext());
            toolbar.setNavigationIcon(homeDrawable);
    
            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);
                    }
                }
            });
        }
    
        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();
                        homeDrawable.setProgress(slideOffset);
                    }
                });
                anim.setInterpolator(new DecelerateInterpolator());
                anim.setDuration(400);
                anim.start();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2017-05-10
      • 1970-01-01
      • 2015-03-02
      • 1970-01-01
      • 1970-01-01
      • 2015-07-28
      • 2015-01-22
      • 2015-11-20
      相关资源
      最近更新 更多