A transition animation compatible Library.
Android5.0之后为我们提供了许多炫酷的界面过渡效果,其中共享元素过渡也是很有亮点的一个效果,但这个效果只能在Android5.0之后使用,那今天我们就来将共享元素过渡效果兼容到Android4.0,让5.0之前的手机也可以体验这么炫酷的效果吧。
A transition animation compatible Library.
兼容Android5.0之后转场动画至Android4.0。
github地址:https://github.com/zhangke3016/TranslationCompat
依惯例,首先来说下本文的行文思路吧:
一、页面过渡兼容库的使用
二、页面过渡兼容库实现原理浅析
三、用兼容库将开源项目MaterialLogin动画效果兼容至Android4.0
MaterialLogin
原项目地址:MaterialLogin将动画效果兼容至Android4.0
Translation
Translation
一、页面过渡兼容库的使用
使用这个兼容库也很简单,首先,在要控制跳转的页面调用TransitionController.getInstance().startActivity方法来实现跳转,在其中主要是传入当前界面要过渡到另一页面的过渡元素View,以及另一个页面对应共享元素的View id值。
然后,在跳转到的第二个页面调用TransitionController.getInstance().show方法来实现元素的过渡,传入参数也很简单。
最后呢,在页面返回的时候,调用TransitionController.getInstance().exitActivity方法即可。
这样一个完整的界面过渡动画基本就可以使用了,当然,为了让实现的效果更炫酷,加入了对过渡动画状态的监听,可以在动画结束时加入自己的操作,为方便起见,兼容库包含圆形元素过渡:调用ViewAnimationCompatUtils.createCircularReveal方法既可实现元素以圆形展开和收起,使用方式和ViewAnimationUtils类一致,以及矩形元素过渡:调用:View www.feihuayl.cn AnimationCompatUtils.createRectReveal方法既可实现元素以矩形方式以左、上、右、下四个方向展开。
具体代码如下:
//参数一:当前Activity
//参数二:跳转意图
//参数三:当前页面跳转至下一页面的View
//参数四:下一页面关联的View id
TransitionController.getInstance().startActivity(this,new Intent(this, RegisterActivity.class),fab,R.id.fab);
//跳转后页面调用:
TransitionController.getInstance().show(this,getIntent());
可在show方法调用之前设置监听:
TransitionController.getInstance().setEnterListener(new TransitionCustomListener() {
@Override
public void onTransitionStart(Animator animator) {
}
@Override
public void onTransitionEnd(Animator www.feiyunyl.cn animator) {
}
@Override
public void onTransitionCancel(Animator animator) {
}
});
//界面退出的时候调用
TransitionController.getInstance().www.yghrcp88.cn exitActivity(PageDetailActivity.this);
//增加界面圆形转换动画
// 用法及参数和ViewAnimationUtils一致
ViewAnimationCompatUtils.createCircularReveal(cvAdd, cvAdd.getWidth()/2,0, fab.getWidth() / 2, cvAdd.getHeight());
//增加界面矩形转换动画
Animator mAnimator = ViewAnimationCompatUtils.createRectReveal( nsv, 0, nsv.getHeight(),ViewAnimationCompatUtils.RECT_TOP);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
二、页面过渡兼容库实现原理浅析
先讲了这个兼容库的用法,现在来聊聊它是怎么实现的,可以把主要实现细分六步:
1、获取跳转页面过渡元素的位置
2、将跳转过渡元素的位置传给下一个页面
3、在跳转到的页面获取位置信息并创建相同宽高大小的元素和其覆盖屏幕的父容器,并将新创建的元素添加到父容器中,而父容器添加至根视图中
4、获取跳转到的页面元素截图并将其设为创建元素的背景
5、将当前新元素位置与跳转到页面对比获取缩放比例与移动距离并开始动画,结束后将父容器隐藏
6、界面返回时将创建的父容器重新添加至下一个页面动画实现,将创建的元素以动画形式返回初始位置,结束后移除父容器
1、获取跳转页面过渡元素的位置
//rect 来存储共享元素位置信息
Rect rect = new Rect();
// 获取元素位置信息
view.getGlobalVisibleRect(rect);
1
2
3
4
1
2
3
4
2、将跳转过渡元素的位置传给下一个页面
// 将位置信息附加到 intent 上
intent.setSourceBounds(rect);
intent.putExtra(TRANSITION_NEXT_ID, nextShowViewId);
1
2
3
1
2
3
3、在跳转到的页面获取位置信息并创建相同宽高大小的元素和其覆盖屏幕的父容器,并将新创建的元素添加到父容器中,而父容器添加至根视图中
View virtalView = new View(activity);
Bitmap cacheBitmap = BitmapUtil.getCacheBitmapFromView(next_view);
// 获取上一个界面中,元素的宽度和高度
final int mOriginWidth = mRect.right - mRect.left;
final int mOriginHeight = mRect.bottom - mRect.top;
getBundleInfo(next_view,mOriginWidth,mOriginHeight,mRect);
//创建覆盖屏幕的父容器
mContainer = new FrameLayout(activity);
FrameLayout.LayoutParams mContainerParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
//父容器添加至根视图中
parent.addView(mContainer,mContainerParams);
if (mBgColor!=-1)
mContainer.setBackgroundColor(ContextCompat.getColor(activity, mBgColor));
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(mOriginWidth, mOriginHeight);
params.setMargins(mRect.left, mRect.top - BarUtils.getActionBarHeight(activity) -getStatusBarHeight(activity), mRect.right, mRect.bottom);
virtalView.setBackgroundDrawable(new BitmapDrawable(activity.getResources(), cacheBitmap));
//创建相同宽高大小的元素
virtalView.setLayoutParams(params);
//将新创建的元素添加到父容器中
mContainer.addView(virtalView);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
4、获取跳转到的页面元素截图并将其设为创建元素的背景
//获取跳转到的页面元素截图
Bitmap cacheBitmap = BitmapUtil.getCacheBitmapFromView(next_view);
//将其设为创建元素的背景
virtalView.setBackgroundDrawable(http://www.zhenloyl88.cn/ new BitmapDrawable(activity.getResources(), cacheBitmap));
/**
* 获取一个 View 的缓存视图
*
* @param view
* @return
*/
public static Bitmap getCacheBitmapFromView(View view) {
final boolean drawingCacheEnabled = true;
view.setDrawingCacheEnabled(drawingCacheEnabled);
view.buildDrawingCache(drawingCacheEnabled);
final Bitmap drawingCache = view.getDrawingCache();
Bitmap bitmap;
if (drawingCache != null) {
bitmap = Bitmap.createBitmap(drawingCache);
view.setDrawingCacheEnabled(false);
} else {
bitmap = null;
}
return bitmap;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
5、将当前新元素位置与跳转到页面对比获取缩放比例与移动距离并开始动画,结束后将父容器隐藏
//将当前新元素位置与跳转到页面对比获取缩放比例与移动距离
getBundleInfo(next_view,mOriginWidth,mOriginHeight,mRect);
//开始动画
runEnterAnim(virtalView,next_view,mContainer);
/**
* 计算缩放比例,以及位移距离
*
* @param
*/
private void getBundleInfo(View mView,int mOriginWidth,int mOriginHeight,Rect mRect) {
// 计算缩放比例
mScaleBundle.putFloat(SCALE_WIDTH, (float) mView.getWidth() / mOriginWidth);
mScaleBundle.putFloat(SCALE_HEIGHT, (float) mView.getHeight() / mOriginHeight);
Rect rect = new Rect();
mView.getGlobalVisibleRect(rect);
// 计算位移距离
mTransitionBundle.putFloat(TRANSITION_X, (rect.left+(rect.right - rect.left) / 2) - (mRect.left + (mRect.right - mRect.left) / 2));
mTransitionBundle.putFloat(TRANSITION_Y, (rect.top + (rect.bottom - rect.top) / 2) - (mRect.top + (mRect.bottom - mRect.top) / 2));
}
/**
* 模拟入场动画
*/
private void runEnterAnim(View next_view,final View realNextView,final FrameLayout mContainer) {
next_view.animate()
.setInterpolator(new LinearInterpolator())
.setDuration(300)
.scaleX(mScaleBundle.getFloat(SCALE_WIDTH))
.scaleY(mScaleBundle.getFloat(SCALE_HEIGHT))
.translationX(mTransitionBundle.getFloat(TRANSITION_X))
.translationY(mTransitionBundle.getFloat(TRANSITION_Y))
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
realNextView.setVisibility(View.GONE);
if (mTransitionCustomListener!=null){
mTransitionCustomListener.onTransitionStart(animation);
}
}
@Override
public void onAnimationEnd(Animator animation) {
mContainer.setVisibility(View.GONE);
realNextView.setVisibility(View.VISIBLE);
if (mTransitionCustomListener!=null){
mTransitionCustomListener.onTransitionEnd(animation);
}
}
@Override
public void onAnimationCancel(Animator animation) {
if (mTransitionCustomListener!=null){
mTransitionCustomListener.onTransitionCancel(animation);
}
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
6、界面返回时将创建的父容器重新添加至下一个页面动画实现,将创建的元素以动画形式返回初始位置,结束后移除父容器
/**
* 模拟退场动画
*/
public void exitActivity(final Activity activity) {
if (nResId!=-1 && mContainer!=null){
//先将创建的父容器从上一个页面移除
((ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT)).removeView(mContainer);
activity.finish();
activity.overridePendingTransition(0,0);
//将创建的父容器重新添加至下一个页面
((ViewGroup) mFirstActivity.findViewById(Window.ID_ANDROID_CONTENT)).addView(mContainer);
mContainer.setVisibility(View.VISIBLE);
//开始动画
mContainer.getChildAt(0).animate()
.setInterpolator(new LinearInterpolator())
.setDuration(300)
.scaleX(1)
.scaleY(1)
.translationX(0)
.translationY(0)
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
mFirstView.setVisibility(View.INVISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
mFirstView.setVisibility(View.VISIBLE);
mContainer.setVisibility(View.GONE);
//结束后移除父容器
((ViewGroup) mFirstActivity.findViewById(Window.ID_ANDROID_CONTENT)).removeView(mContainer);
mContainer.removeAllViews();
mContainer = null;
mFirstView = null;
mFirstActivity =null;
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
}else{
activity.finish();
activity.overridePendingTransition(0,0);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
三、用兼容库将开源项目MaterialLogin动画效果兼容至Android4.0
这里就简单说下兼容MaterialLogin的实现,
首先,界面跳转,调用TransitionController.getInstance().startActivity(this,new Intent(this, RegisterActivity.class),fab,R.id.fab);方法既可,
之后,跳转至注册页面,调用TransitionController.getInstance().setEnterListener设置动画监听,在过渡动画结束时,调用ViewAnimationCompatUtils.createCircularReveal显示圆形展开效果,最后返回调用TransitionController.getInstance().exitActivity(RegisterActivity.this);,炫酷的登录页面就实现啦。
A transition animation compatible Library.的更多相关文章
- css3 transition animation nick
时光转眼即逝,又到周六了,今天写点某部分人看不起的css玩玩! 转换 转换属性transform: 浏览器前缀: -webkit-transform;-o-transform;-moz-transfo ...
- Atitti css transition Animation differ区别
Atitti css transition Animation differ区别 1.1. transition的优点在于简单易用,但是它有几个很大的局限. 1 1.2. Transition ...
- Atitti css transition Animation differ区别
Atitti css transition Animation differ区别 1.1. transition的优点在于简单易用,但是它有几个很大的局限. 1 1.2. js 动态改变 st ...
- css3动画transition animation
CSS动画简介 transition animation transition过渡:css3通过transitions属性引入时间概念,通过开始.结束状态自动计算中间状态,实现状态改变的过渡效果 ...
- ..\OBJ\CAN.axf: Error: L6411E: No compatible library exists with a definition of startup symbol __main.
..\OBJ\CAN.axf: Error: L6411E: No compatible library exists with a definition of startup symbol __ma ...
- CSS3 & transition & animation
CSS3 & transition & animation https://developer.mozilla.org/en-US/docs/Web/CSS/transition-ti ...
- CSS动画-transition/animation
HTML系列: 人人都懂的HTML基础知识-HTML教程(1) HTML元素大全(1) HTML元素大全(2)-表单 CSS系列: CSS基础知识筑基 常用CSS样式属性 CSS选择器大全48式 CS ...
- CSS Transform / Transition / Animation 属性的区别
back21 Jun 2011 Category: tech Tags: css 最近想UI的动画转到css3能吃进3d加速的属性上面来以加强动画的连贯性.只是对于css几个新加的属性不太熟悉,常常容 ...
- css3的新特性transform,transition,animation
一.transform css3引入了一些可以对网页元素进行变换的属性,比如旋转,缩放,移动,或者沿着水平或者垂直方向扭曲(斜切变换)等等.这些的基础都是transform属性 transform属性 ...
随机推荐
- AVL树的左旋右旋理解 (转)
AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增加和删除可能需要通过一次或多 ...
- Yii2 自动更新时间created_at updated_at
创建model之后,新建一条记录,结果设计的表中created_at 字段 updated_at 字段 都是datetime 类型的,却不能自动插入当前时间.查看了资料,解决如下: 1.在class ...
- KVM虚拟化技术
KVM虚拟化技术 Qemu-kvm kvm virt-manager VNC Qemu-kvm创建和管理虚拟机 一.KVM简介 KVM(名称来自英语:Kernel-basedVirtual Machi ...
- 后台action处理数据传递给前台界面
package com.renmai.util; import java.io.IOException; import javax.servlet.http.HttpServletResponse; ...
- Hibernate—第一个案例
百度百科上是这样写道的:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可 ...
- 【web开发学习笔记】ibatis学习总结
ibatis学习总结 ibatis数据库配置文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCT ...
- ADO.NET与Oracle(一):获取多行记录集
近期接触ADO.NET和Oracle.将我寻常遇到的一些问题和大家共享. 我认为要想入门ADO.NET操作Oracle,最主要的要求就是要会通过ADO.NET更新Oracle中的数据. 该文简单讲些利 ...
- JQuery Kendo UI使用技巧总结
Kendo UI开发总结 By Gloomyfish on 2013-04-25 在Grid中支持分页刷新: scrollable: {virtual : true }, 在Gr ...
- Linux shell的&&和||--转载
Linux shell的&&和|| shell 在执行某个命令的时候,会返回一个返回值,该返回值保存在 shell 变量 $? 中.当 $? == 0 时,表示执行成功:当 $? ...
- Android(java)学习笔记171:Service生命周期
1.Service的生命周期 Android中的Service(服务)与Activity不同,它是不能和用户交互,不能自己启动的,运行在后台的程序,如果我们退出应用的时候,Servic ...