Android 转场动画合集
项目背景:mvvm+组件化,然后由于领导要求,使用MainActivity为主界面,各种业务使用Fragment处理。所以~ 由于单独Activity+N Fragment 的方式,经过十多天的试错,我确认一件事情。再确认过架构方式后一定要了解下业务场景和使用技术栈。不然会导致身心俱疲——下一篇记录 组件化方式中使用 MainActivity + N Fragment方式怎么适配 组件化。
目录
1、界面转跳 转场动画;
方案一:使用 ARouter 自带 withTransition 设置转场动画。
方案二:使用ViewAnimationUtils 实现动画,配合addOnLayoutListener 监听 控制rootView显隐,达到视觉效果的转场。
方案三:使用Android官方推荐的共享元素方式
使用 FragmentTransaction
使用 TransitionSet
使用 MaterialContainerTransform
2、Fragment add Fragment 动画不生效问题记录。
1、界面转跳 转场动画;
方案一:使用 ARouter 自带 withTransition 设置转场动画。
// 普通跳转
ARouter.getInstance().build("/test/activity")
.withTransition(R.anim.slide_in_right, R.anim.slide_out_left) // 设置转场动画
.navigation(this);
slide_in_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="100%"
android:toXDelta="0%" />
</set>
slide_out_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0%"
android:toXDelta="-100%" />
</set>
优点:实现简单,不用二次封装
缺点:无法实现复杂的动画。
方案二:使用ViewAnimationUtils 实现动画,配合addOnLayoutListener 监听 控制rootView显隐,达到视觉效果的转场。
转跳前可以获取按钮位置xy值
binding.tvRouter.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int centerX = (v.getLeft() + v.getRight()) / 2;
int centerY = (v.getTop() + v.getBottom()) / 2;
LogUtils.e("centerX: " + centerX );
LogUtils.e("centerY: " + centerX );
ARouter.getInstance().build(RouterActivityPath.Login.PAGER_LOGIN)
.withInt("centerX", centerX)
.withInt("centerY", centerY)
.navigation(getActivity());
}
});
转跳界面:获取前页面传递过来xy值,设置一些想要的动画效果。
centerX =getIntent().getIntExtra("centerX",0);
centerX =getIntent().getIntExtra("centerY",0);
binding.parent.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
binding.parent.removeOnLayoutChangeListener(this);
float finalRadius = (float) Math.hypot(v.getWidth(), v.getHeight());
CircularRevealUtil.startCircularReveal(v, centerX, centerY, 0, finalRadius);
}
});
CircularRevealUtil : 作了一个示例,圆形揭示
/**
* 开始圆形揭示动画
*
* @param view 要显示的视图
* @param centerX 动画的中心X坐标
* @param centerY 动画的中心Y坐标
* @param startRadius 动画起始半径
* @param endRadius 动画结束半径
*/
public static void startCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius) {
Animator anim = ViewAnimationUtils.createCircularReveal(view, centerX, centerY, startRadius, endRadius);
view.setVisibility(View.VISIBLE);
anim.start();
}
优点:可以定制复杂的转场动画
缺点:不易封装,实现难度,性能消耗等
方案三:使用Android官方推荐的共享元素方式
// 在第一个Activity中启动第二个Activity
Intent intent = new Intent(this, SecondActivity.class);
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(
this,
Pair.create(sharedView, "shared_element_transition")
);
startActivity(intent, options.toBundle());
在布局文件中,为共享元素设置 android:transitionName
:
<!-- activity_first.xml -->
<ImageView
android:id="@+id/sharedView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/sample_image"
android:transitionName="shared_element_transition" />
<!-- activity_second.xml -->
<ImageView
android:id="@+id/sharedView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/sample_image"
android:transitionName="shared_element_transition" />
使用 FragmentTransaction
对于 Fragment
之间的共享元素动画,可以使用 FragmentTransaction
类来设置共享元素。
在第一个 Fragment
中启动第二个 Fragment
:
Fragment secondFragment = new SecondFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, secondFragment);
transaction.addToBackStack(null);
transaction.addSharedElement(sharedView, "shared_element_transition");
transaction.commit();
在布局文件中,为共享元素设置 android:transitionName
<!-- fragment_first.xml -->
<ImageView
android:id="@+id/sharedView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/sample_image"
android:transitionName="shared_element_transition" />
<!-- fragment_second.xml -->
<ImageView
android:id="@+id/sharedView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/sample_image"
android:transitionName="shared_element_transition" />
使用 TransitionSet
如果需要同时使用多种动画效果,可以使用 TransitionSet
来组合多个动画效果。
TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(new ChangeBounds());
transitionSet.addTransition(new ChangeTransform());
transitionSet.addTransition(new ChangeImageTransform());
getWindow().setSharedElementEnterTransition(transitionSet);
getWindow().setSharedElementReturnTransition(transitionSet);
使用 MaterialContainerTransform
MaterialContainerTransform
是 Android Material Design 提供的一个组件,可以用于容器转换动画,适用于 Activity
和 Fragment
之间的共享元素过渡。
FragmentTransaction transaction = getFragmentManager().beginTransaction();
MaterialContainerTransform transform = new MaterialContainerTransform();
transform.setDuration(300);
secondFragment.setSharedElementEnterTransition(transform);
transaction.addSharedElement(sharedView, "shared_element_transition");
transaction.replace(R.id.fragment_container, new SecondFragment());
transaction.addToBackStack(null);
transaction.commit();
在布局文件中,为共享元素设置 android:transitionName
<!-- fragment_first.xml -->
<View
android:id="@+id/sharedView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:transitionName="shared_element_transition" />
<!-- fragment_second.xml -->
<View
android:id="@+id/sharedView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:transitionName="shared_element_transition" />
2、Fragment add Fragment 动画不生效问题记录。
其实写这篇文章最重要的是想记录这个问题,我卡了一天。怀疑了FragmentTransaction封装,怀疑组件化结构。任何动画设置均不成功。最后看到自己布局里使用的Fragment容器。
<androidx.fragment.app.FragmentContainerView
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
FragmentContainerView 会导致 Fragment转场动画不生效。
FragmentContainerView 会导致 Fragment转场动画不生效。
FragmentContainerView 会导致 Fragment转场动画不生效。
重要的话说三遍