Android使用动画进行Fragment、Activity的切换

我们知道有些Fragment、Activity的跳转花时间比较长。这时候通过给跳转加上一些动画效果可以让用户感受不到这样等待,给用户很好的应用体验。个人觉得PayPal的动画效果就做得蛮好的。

给Fragment的转换添加动画

这里就难得想例子了。直接吧官方给的例子修改的一下进行讲解(官方的例子是一个用翻转动画实现Fragment切切换的例子):

先定义好四个Animator。分别是:

  • enter_animator: 这个动画将作用于将被添加的Fragment中的View
  • exit_animator: 这个动画作用于将会被移除的Fragemnt中的View
  • pop_enter_animator: 这个动画作用于FragmentManager#popBackStack()方法调用或者back键按后,将被添加的Fragment中的View
  • pop_exit_animator: 这个动画作用于FragmentManager#popBackStack()方法调用或者back键按后,将被移除的Fragment中的View

enter_animtor.xml


    
    
    

    

这里定义了一个属性AnimatorSet,这个set中有三个ObjectAnimator。

第一个是在开始的时候,就将将要出现的Fragment中的View的透明度设置为透明。

第二个是对将要出现的Fragment中的View进行rotationY的变换。

第三个是在动画转换到一半的时候将将要出现的Fragment中的View的透明设置为完全不透明

exit_animator.xml


    

    

其中,第一个ObjectAnimator是对将要消失的Fragment中的View进行rotaionY的变换。

第二个是在动画执行到一半的时候对将要的消失的Fragment中的View透明度转换为透明。

后面两个动画,我就不再进行详细的介绍了。相当于前面这两个动画的逆过程。

pop_enter_animator.xml



    

    

    

pop_exit_animator.xml



    

    

下面是Activity的xml:




    

Activity的代码:

class CardFlipActivity : AppCompatActivity() {

    //是否现在背面(也就是第二个Fragment)
    private var mShowingBack = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_card_flip)

        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                    .add(R.id.container, CardFrontFragment())
                    .commit()
        }
        
        btn.setOnClickListener {
            flip()
        }
    }

    private fun flip() {
        if (mShowingBack) {
            supportFragmentManager.popBackStack()
            mShowingBack = false
            return
        }
        mShowingBack = true
        supportFragmentManager
                .beginTransaction()
                //为Fragment转换设置动画
                .setCustomAnimations(R.animator.enter_animator,
                        R.animator.exit_animator,
                        R.animator.pop_enter_animator,
                        R.animator.pop_exit_animator)
                .replace(R.id.container, CardBackFragment())
                .addToBackStack(null)
                .commit()
    }

    override fun onBackPressed() {
        mShowingBack = false
        super.onBackPressed()
    }

    /**
     * 正面Fragment(第一个Fragment)
     */
    class CardFrontFragment : Fragment() {
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, 
                                  savedInstanceState: Bundle?): View? {
            return inflater.inflate(R.layout.fragment_card_front, container, false)
        }
    }

    /**
     * 背面Fragment(第二个Fragment)
     */
    class CardBackFragment : Fragment() {
        override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, 
                                  savedInstanceState: Bundle?): View? {
            return inflater.inflate(R.layout.fragment_card_back, container, false)
        }
    }
}

很简单这里我就不详细讲了。

重点就是flip方法中为Fragment切换设定动画的方法。那个四个参数可以分别对应动画去看。然后不太清楚可以直接跳进行看。之前在四个动画的介绍中已经说了,这里我就不太想再说了。

没错为Fragment设置动画就是这么easy!!!

给Activity的转换添加过渡动画

为Activity设置动画仍然很简单。

为Activity将借助于Transition来进行实现。前面已经讲了Transition了。这里就直接通过例子来进行讲解了。

定义Activity过渡动画

定义Activity的过渡动画仍然可以在xml和代码中进行定义。

在styles.xml定义的过渡动画会对所有的Activity使用。在代码中进行定义的过渡动画只会对被定义的Activity使用

下面是在styles.xml中定义的例子:




    

其中给android:windowEnterTransition、android:windowExitTransition这个两个动画需要继承自Visibility才行。比如说:Explode、Slide、Fade

下面是在代码中对应的定义:

with(window){
    requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)

    enterTransition = Slide(Gravity.BOTTOM)
    exitTransition = Slide(Gravity.TOP)

    sharedElementEnterTransition = 
    TransitionInflater.from(this@FirstAnimationActivity)
            .inflateTransition(R.transition.change_image_transform)
    sharedElementExitTransition = 
    TransitionInflater.from(this@FirstAnimationActivity)
            .inflateTransition(R.transition.change_image_transform)
}

其中change_image_transform.xml定义如下:



    
    

这个很简单就不介绍了。

使用指定的Transition来启动不带共享View的Activity

下面是FirstAnimationActivity的xml:




    

通过定义好的Transition来启动Activity就只需要想下面一样进行定义:

class FirstAnimationActivity : AppCompatActivity() {

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_first_animation)

        btn.setOnClickListener{
            startActivity(Intent(this, SecondAnimationActivity::class.java),
                    ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle())
        }
    }
}

是不是很简单就是加上ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle()作为startActivity的参数就行了。

使用Transition来启动带有单个共享View的Activity

这个也很简单,这里讲以共享一个ImageView的来作为例子。

定义共享View的方式有两种:

  • 在xml中通过transitionName来进行定义。
  • 在代码中通过ViewCompat.setTransitionName()来动态进行设置

一般如果View是在xml中进行定义的就用第一种方式,如果View是在代码中进行定义的就用第二种。

在xml中定义

下面是FirstAnimationActivity中修改的代码(其中xml仍然是上面的xml)

class FirstAnimationActivity : AppCompatActivity() {

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onCreate(savedInstanceState: Bundle?) {
...
        btn.setOnClickListener{
            startActivity(Intent(this, SecondAnimationActivity::class.java),
                    ActivityOptionsCompat.makeSceneTransitionAnimation(this,
                            iv, "iv").toBundle())
        }
    }
}

这个给ActivityOptionsCompat的makeSceneTransitionAnimation加了两个参数,第一个是要当前layout中要共享的View,第二个是在另外的Activity中对应的View的transitionName。

下面是SecondAnimationActivity中的xml:




    

    


这里需要注意的有一个地方就是ImageView中的transitionName,这个就是前面makeSceneTransitionAnimation的新增的第二个参数。

在代码中定义

在代码中定义一般是如果在代码中动态生成View的情况下进行使用的。这里就不在代码中生成了。直接使用xml中的ImageView进行举例。

下面是SecondAnimationActivity的代码:

class SecondAnimationActivity : AppCompatActivity() {
    
    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_second_animation)
        ViewCompat.setTransitionName(iv, "iv")
    }
}

像这样定义后,你就可以将xml中ImageView中的transitionName属性去掉了!!!

使用Transition来启动带有多个共享View的Activity

当我们有多个View需要在两个View中进行共享的时候该怎么办?其实很简单基本和单个的情况是一样的。

只有下面的的一点不同:

下面通过代码举个例子,具体的例子我就写了:

startActivity(Intent(this, SecondAnimationActivity::class.java),
        ActivityOptionsCompat.makeSceneTransitionAnimation(this,
        Pair(view1, "view1"),
        Pair(view2, "view2")...).toBundle())

总结

这篇博客主要就是两个内容。

  • 一个是给Fragment的跳转设置动画,通过setCustomAnimations进行设置
  • 然后就是为Activity设定跳转的过渡动画。这个重要的就是ActivityOptionsCompat的makeSceneTransitionAnimation静态方法的使用

你可能感兴趣的:(Android使用动画进行Fragment、Activity的切换)