Android 共享元素动画 向下兼容android5.0版本
概述:
最近项目中需要在启动过后弹出倒计时的广告,倒计时结束后跳转到首页并实现类似共享元素动画,实现广告的图片与首页中的某个控件实现共享元素动画。
我刚接受到这个需求的时候,想到的就是android默认的共享元素动画。但在实际的开发中并不容易,主要是首页是由多个fragment实现,测试中共享元素动画就不起作用了,也不太了解这共享元素动画的原理。就在自己没有一点思路的情况下,打开百度搜索了相关文章,还真找到了,先给个链接。之所以写这篇文章是对我看的这篇文章的一个扩展。因为虽然作者写的也比较详细,但对于开发者来说。时间成本还是很宝贵的。看了他的文章 需要自己去理一下。由于作者贴的代码不是很全,所以便有了此篇文章,也同时非常感谢作者提供的宝贵的资料。
原理:
定义页面: B页面-广告倒计时页面(ActivityB),A页面(CFragment)-->寄主(ActivityA)
首先获得B页面控件的宽和高以及控件显示在屏幕中的位置,然后通过Intent传值的方式传递到A页面的碎片CFragment
Intent intent = new Intent(ActivityB.this, ActivityA.class);
intent.putExtra(IMAGE_URL_EXTRA, imageUrl);
intent.putExtra(VIEW_INFO_EXTRA, /* start values */ captureValues(imageView));
startActivity(intent);
overridePendingTransition(0, 0);
finish();
private Bundle captureValues(@NonNull View view) {
Bundle b = new Bundle();
int[] screenLocation = new int[2];
view.getLocationOnScreen(screenLocation);
b.putInt(PROPNAME_SCREENLOCATION_LEFT, screenLocation[0]);
b.putInt(PROPNAME_SCREENLOCATION_TOP, screenLocation[1]);
b.putInt(PROPNAME_WIDTH, view.getWidth());
b.putInt(PROPNAME_HEIGHT, view.getHeight());
return b;
}
其实是通过B页面传递的数据,然后进行A页面需要共享元素控件的位移和缩放,重要的事情说一遍。就是对A页面的控件进行位移和缩放的动画 跟B页面没有半毛线关系。B页面主要是提供一些参数。具体实现动画的是在A页面。
接下来我们在看下CFragment
如果是网络图片需要在图片加载完成过后进行动画操作:
Glide.with(this).asBitmap().load(imageUrl).into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
mDestinationView.setImageBitmap(resource);
onUiReady();
}
});
把A页面需要共享元素控件的大小设置为B页面的显示图片的大小。也是通过位移和缩放动画 这样就可以给我们错觉,也就是由B页面控件过渡到A页面的控件 从而实现类似于共享元素动画的效果
private void prepareScene() {
int[] locations = new int[2];
mDestinationView.getLocationOnScreen(locations);
mEndXValues = locations[0];
mEndYValues = locations[1];
mEndWidth = mDestinationView.getWidth();
mEndHeight = mDestinationView.getHeight();
mDestinationView.setScaleX(getScaleX());
mDestinationView.setScaleY(getScaleY());
mDestinationView.setTranslationX(getDeltaX());
mDestinationView.setTranslationY(getDeltaY());
}
private void runEnterAnimation() {
// We can now make it visible
mDestinationView.setVisibility(View.VISIBLE);
// finally, run the animation
mDestinationView.animate()
.setDuration(DEFAULT_DURATION)
.setInterpolator(DEFAULT_INTERPOLATOR)
.scaleX(1f)
.scaleY(1f)
.translationX(0)
.translationY(0)
.start();
}
private float getScaleX(){
return scaleDelta(mStartWidth, mEndWidth);
}
private float getScaleY(){
return scaleDelta(mStartHeight, mEndHeight);
}
private int getDeltaX(){
return translationDelta(mStartXValues, mEndXValues);
}
private int getDeltaY(){
return translationDelta(mStartYValues, mEndYValues);
}
private int translationDelta(int startPosition,int endPosition){
return startPosition - endPosition;
}
private float scaleDelta(int startValue,int endValue){
if (endValue == 0)return 1;
return startValue/(endValue * 1.0f);
}
核心代码就是这些,当然了退出页面A页面 进入到B页面也需要退出动画。具体调用是在按返回键或则home键
private void runExitAnimation() {
mDestinationView.animate()
.setDuration(DEFAULT_DURATION)
.setInterpolator(DEFAULT_INTERPOLATOR)
.scaleX(getScaleX())
.scaleY(getScaleY())
.translationX(getDeltaX())
.translationY(getDeltaY())
.withEndAction(new Runnable() {
@Override
public void run() {
mActivity.finish();
mActivity.overridePendingTransition(0, 0);
}
}).start();
}
直接复制就可以用了
如有需要 源码链接附上 写的不是很规范还望谅解 :