丨版权说明 : 《Android转场动画和共享元素动画兼容5.0以下版本的实现》于当前CSDN博客和乘月网属同一原创,转载请说明出处,谢谢。
一款APP让人赏心悦目的APP,动画是它并不可少的部分,Android提供很多原生动画方式如帧动画,属性动画等,也提供了一些组件动画套装,如Activity间的过渡跳转动画,还有Fragment,Dialog等展示动画。本文只讲Android转场动画和共享元素动画。
CySharedElementTransition
A compat library of android shared-element transition for lower api. 一个为Android较低版本api提供Android共享元素转场动画的兼容库。
开源库地址:https://github.com/ausboyue/CySharedElementTransition
Activity转场动画
先看效果图
Activity降落过渡动画 ↓↓↓
Activity左滑过渡动画 ↓↓↓
这些动画一定程度上提高了良好的用户交互视觉感受,但是还有更高层次的过渡动画,那就是基于控件(View)级别的过渡动画(共享元素动画的精髓)。
共享元素动画
Google在Android5.0时开始集成了更多更全面更易于开发者定义的的转场动画和共享元素动画。
下面我们看看示例Google Play:
当你点击app logo时,这个logo会通过动画引导出下一个界面,引导过程中逐渐显示界面剩余的所有元素(View),完成非常平滑界面过渡。由于录制和图片压缩的原因,效果图画面比较模糊,画面有白闪,卡顿现象,真实效果大家可以下载体验下。
然而作为挖坑大师的Google从不吝啬在自己的每一个产品上给开发者挖坑--Android5.0以下版本无法使用该类型的动画
这就意味着如果想让自己的APP气质提高一个档次,在应用这些牛逼的动画时需要这样做?
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
Toast.makeText(context, "请先升级5.0及以上的系统或换好一点的手机吧!", Toast.LENGTH_SHORT).show();
finish();
return;
}
好主意,专治各种不服!可是直到有一天产品小哥突然敲敲地凑到你的耳边对你说:↓↓↓
我......!!! 那个,请转告老板,把工资给我结一下,谢谢。
可不能这么快就认怂,没有官方的支持,我们就走“曲线救国”爬坑之路呗。虽然实现起来有些麻烦,但也没那么可怕,下面正式进入主题。
ActivityA跳转至ActivityB
简述流程
- 获取ActivityA元素信息(如View的大小,位置,id)即属性值材料,作为转场动画的初始值
- ActivityA通过Intent传递给ActivityB
- ActivityB设为全透明(Window和Content Layout以及元素View皆为透明)
- ActivityB读取Intent中的初始值信息并为其元素准备转场动画
- ActivityB执行共享元素转场动画
graph LR
A[获取ActivityA的元素信息]-->B[构建Intent]
B-->|start跳转|D{ActivityB读取Intent转场信息}
C[ActivityB设为全透明]-->D
D-->E[ActivityB准备转场动画]
E-->F[ActivityB执行转场动画]
我们以上述google play的转场动画为例,ActivityA上有个app logo即为ImageViewA,ActivityB的即为ImageViewB,logo图片的资源地址为imgUrl。下面用代码示例走流程:
详细代码流程
1. 获取ActivityA的元素信息
private Bundle createMaterials(View view) {
// 位置坐标
int[] location = new int[2];
view.getLocationOnScreen(location);
Bundle b = new Bundle();
int left = location[0];
int top = location[1];
// 宽高大小
int width = view.getWidth();
int height = view.getHeight();
// 传入Bundle
b.putInt("left", left);
b.putInt("top", top);
b.putInt("width", width);
b.putInt("height", height);
return b;
}
2. 在ActivityA中构建Intent
// 获取初始值材料
Bundle materials=createMaterials(imageViewA);
Intent intent = new Intent(activityA, ActivityB.class);
intent.putExtra(EXTRA_IMG_URL, imgUrl);
// 传入构建好的View属性值材料
intent.putExtra(EXTRA_VIEW_ATTRS_MATERIALS , materials);
startActivity(intent);
// 禁止系统默认动画
overridePendingTransition(0, 0);
3. ActivityB设为全透明
- Window设为透明,在ActivityB主题(style)中设置
<style name="WindowTransparent" parent="AppTheme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
- Layout以及元素View设为透明
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_head"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="centerCrop"
android:visibility="invisible"/>
</LinearLayout>
4. ActivityB读取Intent转场信息
private void prepareTransition() {
int[] location = new int[2];
imageViewB.getLocationOnScreen(location);
// 移动到ActivityA元素imageViewA同样的位置
deltaX = imageViewALeft - location[0];
deltaY = imageViewATop - location[1];
imageViewB.setTranslationX(deltaX);
imageViewB.setTranslationY(deltaY);
// 缩放到imageViewA同样的大小
scaleX = (float) imageViewAWidth / imageViewB.getWidth();
scaleY = (float) imageViewAHeight / imageViewB.getHeight();
imageViewB.setScaleX(scaleX);
imageViewB.setScaleY(scaleY);
}
5. ActivityB执行共享元素转场动画
private void runEnterAnimation() {
imageViewB.setVisibility(View.VISIBLE);
// 加载图片,如Glide
Glide.with(context).load(imgUrl).into(imageViewB);
// 执行动画
imageViewB.animate()
.setDuration(DEFAULT_DURATION)
.setInterpolator(DEFAULT_INTERPOLATOR)
.scaleX(1f)
.scaleY(1f)
.translationX(0)
.translationY(0)
.start();
}
ActivityB回退至ActivityA
流程比较简单,直接上代码喽:
private void runExitAnimation() {
// 执行回退动画
imageViewB.animate()
.setDuration(DEFAULT_DURATION)
.setInterpolator(DEFAULT_INTERPOLATOR)
.scaleX(scaleX)
.scaleY(scaleY)
.translationX(deltaX)
.translationY(deltaY)
.withEndAction(new Runnable() {
@Override
public void run() {
// 关闭ActivityB
finish();
// 禁止系统默认动画
overridePendingTransition(0, 0);
}
}).start();
}
OK,大体流程如上,Demo效果图如下:
如果想深入地学习,大家可以了解下我的开源库,可供学习,亦可集成到项目中使用。
CySharedElementTransition
A compat library of android shared-element transition for lower api. 一个为Android较低版本api提供Android共享元素转场动画的兼容库。
开源库地址:https://github.com/ausboyue/CySharedElementTransition
ScreenShot
Download from Gradle
Add to your root build.gradle:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
Add the dependency:
dependencies {
implementation 'com.github.ausboyue:CySharedElementTransition:1.0.1'
}
Friendly Hints
If you can\'t download it, maybe you have used the Google\'s repository that you can\'t connect to the Google server.Please open the proxy or top the target repository.As follows(如果你无法下载这个库,你可能使用了google的仓库。请开启代理或者置顶目标仓库,如下所示):
allprojects {
repositories {
maven { url 'https://jitpack.io' } // target repository,be top
jcenter()
google() // Google's repository
}
}
Download from Maven
Add the JitPack repository to your build file:
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
Add the dependency:
<dependency>
<groupId>com.github.ausboyue</groupId>
<artifactId>CySharedElementTransition</artifactId>
<version>1.0.1</version>
</dependency>
Get Started
1. ActivityA jump to ActivityB,when need use "SharedElementTransition"(ActivityA 跳转到ActivityB,当需要用到“共享元素转场动画”时):
-
ActivityA edit code as below(编辑ActivityA 的代码如下):
CySharedElementTransition.startActivity(intent, activityA, view1, view2, view...);
-
ActivityB edit code as below(编辑ActivityB 的代码如下):
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ...... CySharedElementTransition.runEnterAnim(activityB); ...... }
2. ActivityB back to ActivityA(ActivityB Ac回到ActivityA):
-
ActivityB edit code like this(编辑ActivityB 的代码,类似代码如下):
@Override public void onBackPressed() { CySharedElementTransition.runExitAnim(activityB); }
暂无评论内容