android - 添加 fragment 时从汉堡包到箭头图标的过渡动画

标签 android android-fragments animation

我已经实现了主/细节流程,我想在添加 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后,图标只是改变了,没有动画。

最佳答案

先做一些解释。

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

  2. 类是 android.support.v7.graphics.drawable.DrawerArrowDrawable

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

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

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

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

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

那么,你应该在 Activity 中做什么。 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

关于android - 添加 fragment 时从汉堡包到箭头图标的过渡动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38335216/

相关文章:

android - 在 Android 应用程序中使用 Microsoft Access 文件

android - react-native-video 需要很长时间才能开始播放

jquery - 如何使用 scroll top 在 css 中触发动画?

android - Google Maps API key 是否缓存在 Android 上?

android - 多次调用 startLeScan 方法不能正确扫描 BLE 设备

android - ExoPlayer2 - 如何从 fragment 中释放

android - onRequestPermissionsResult 在 HomeActivity 中调用但不在 Fragment 中调用

android - 为什么 getFragmentManager().findFragmentById 返回 null(导致 NullPointerException)

angular - 在表单错误时触发 Angular 动画

javascript - 检测实际可用的计算和处理能力浏览器javascript