0
点赞
收藏
分享

微信扫一扫

使用动画在Fragment之间导航

在Fragment之间进行动画导航的方式有两种:

1.使用Animation或者animator框架;

2.使用Transition框架

术语:

  • enter effect :进入效果。A跳转到B界面,B界面(入场)的变化效果。
  • exit effect :退出效果。A跳转到B界面,A界面(退场)的变化效果。
  • popEnter:B界面返回到A界面,A界面(重入场)的变化效果。
  • popExit:B界面返回到A界面,AB界面(退场)的变化效果。
  • shared element transition: 共享元素动画。AB界面中有共享元素,对此元素的入场(退场)进行动画效果。

用动画框架( Animation Framework)

和平常使用Animation一样,我们需要首先定义资源文件。

<!-- res/anim/fade_out.xml -->
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_shortAnimTime"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:fromAlpha="1"
    android:toAlpha="0" />
<!-- res/anim/slide_in.xml -->
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_shortAnimTime"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:fromXDelta="100%"
    android:toXDelta="0%" />

返回时的界面效果同理:

<!-- res/anim/slide_out.xml -->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_shortAnimTime"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:fromXDelta="0%"
    android:toXDelta="100%" />
<!-- res/anim/fade_in.xml -->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_shortAnimTime"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:fromAlpha="0"
    android:toAlpha="1" />

最后Fragment跳转时,在 [FragmentTransaction.setCustomAnimations()]中使用他们即可。

val fragment = FragmentB()
supportFragmentManager.commit {
    setCustomAnimations(
        enter = R.anim.slide_in,
        exit = R.anim.fade_out,
        popEnter = R.anim.fade_in,
        popExit = R.anim.slide_out
    )
    replace(R.id.fragment_container, fragment)
    addToBackStack(null)
}

用过渡框架(Transition Fragment)

For example, you might want the current fragment to fade out and the new fragment to slide in from the right edge of the screen.

<!-- res/transition/fade.xml -->
<fade xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_shortAnimTime"/>
<!-- res/transition/slide_right.xml -->
<slide xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_shortAnimTime"
    android:slideEdge="right" />

使用的时候则是,在A界面(出场界面)中调用setExitTransition()

在B界面(入场界面)中调用 setEnterTransition()

class FragmentA : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val inflater = TransitionInflater.from(requireContext())
        exitTransition = inflater.inflateTransition(R.transition.fade)
    }
}

class FragmentB : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val inflater = TransitionInflater.from(requireContext())
        enterTransition = inflater.inflateTransition(R.transition.slide_right)
    }
}

共享元素动画

  1. 首先,还是定义xml。
<!-- res/transition/shared_image.xml -->
<transitionSet
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1375"
    android:transitionOrdering="together">
  <changeClipBounds/>
  <changeTransform/>
  <changeBounds/>
  <changeImageTransform/>
</transitionSet>
  1. 其次,要在A B界面中分别标明哪个是共享的元素.用setTransitionName(view, "name")
class FragmentA : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ...
        val itemImageView = view.findViewById<ImageView>(R.id.item_image)
        ViewCompat.setTransitionName(itemImageView, “item_image”)
    }
}

class FragmentB : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        ...
        val heroImageView = view.findViewById<ImageView>(R.id.hero_image)
        ViewCompat.setTransitionName(heroImageView, “hero_image”)
    }
}
  1. 当然,FragmentTransaction也要认得这个动画的共享元素:【 FragmentTransaction.addSharedElement()
val fragment = FragmentB()
supportFragmentManager.commit {
    setCustomAnimations(...)
    addSharedElement(itemImageView, “hero_image”)
    replace(R.id.fragment_container, fragment)
    addToBackStack(null)
}
  1. 最后,要用到第一步中定义的shared_image动画。

通过TransitionInflater把xml转为对象,再在B界面(跳转到的界面)中用Fragment.setSharedElementEnterTransition()即可。

class FragmentB : Fragment() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        sharedElementEnterTransition = TransitionInflater.from(requireContext())
             .inflateTransition(R.transition.shared_image)
    }
}
举报

相关推荐

0 条评论