1:基础
ActivityA 跳转ActivityB只需要四步:
第一步,设置A中view的
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:id="@+id/icon"
android:src="@mipmap/ic_launcher"
android:transitionName="share"
/>
如上,只需要设置transitionName属性。至于值,我们可以随意设置。
第二步:
设置ActivityB的transitionName。
<ImageView
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="@+id/testIcon1"
android:scaleType="centerCrop"
android:src="@mipmap/ic_launcher"
android:transitionName="share" />
第三步设置intent跳转。
var intent = Intent(this, Main2Activity::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
startActivity(
intent, ActivityOptions.makeSceneTransitionAnimation(
this,
icon, "share"
).toBundle()
)
} else {
startActivity(intent)
}
如上所示:
跟正常的startActivity区别就是我们多传了个bundle。
makeSceneTransitionAnimation方法,有三个参数,上下文,共享元素,以及transitionName。
其实到这里,我们已经实现了相关效果。
那第四步是什么呢?
简单来说就是退出时的效果,如果只是使用系统回退,后续就不用考虑了,
如果是我们需要调用finish的话,就可以看到,退出时的效果是错误的
,这里我们需要替换finish为finishAfterTransition方法。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
finishAfterTransition()
}else{
finish()
}
当然,系统给我提供了简便的方法就是:
supportFinishAfterTransition()。
这个方法内部,就是上面判断version的代码。
二:扩展
由于项目中使用的是fresco,所以在使用时,遇到了一些坑,这里记录下:
1:由于从列表跳转详情,图片加载时,跳转没有想要的效果,这里需要在我们跳转的activity添加下面的属性:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.sharedElementEnterTransition = DraweeTransition.createTransitionSet(
ScalingUtils.ScaleType.CENTER_CROP,
ScalingUtils.ScaleType.CENTER_CROP
) // 进入
window.sharedElementReturnTransition = DraweeTransition.createTransitionSet(
ScalingUtils.ScaleType.CENTER_CROP,
ScalingUtils.ScaleType.CENTER_CROP
) // 返回
}
2:添加了上面的代码后,发现进入activityB时,动画效果对了,但是返回时,activityA中设置android:transitionName属性的view不可见了。。
怎么解决呢?
找到startactivity,在他前面添加如下代码:
setExitSharedElementCallback(object : SharedElementCallback() {
//注意[Activity Context]一般为this,如果在Fragment中请使用getActivity(),在BaseFramework中为参数me
override fun onSharedElementEnd(
sharedElementNames: List<String>,
sharedElements: List<View>,
sharedElementSnapshots: List<View>
) {
super.onSharedElementEnd(
sharedElementNames,
sharedElements,
sharedElementSnapshots
)
for (view in sharedElements) {
view.visibility = View.VISIBLE
}
}
})
ok。大功告成
3:ActivityB中使用Glide加载同样会有问题:
解决办法:
1:在进入activity时使用 supportPostponeEnterTransition();
2:加载图片时使用 supportStartPostponedEnterTransition(),如下:
Glide.with(this)
.load(iconUrl)
.listener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
supportStartPostponedEnterTransition();
return false;
}
})
.into(imageView);
4:ActivityB中共享元素是viewpager时:
同上在开始时使用supportPostponeEnterTransition();
viewpager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
viewpager.getViewTreeObserver().removeOnGlobalLayoutListener(this);
//释放
supportStartPostponedEnterTransition();
}
});