实现Android5.0过渡动画兼容库
来源:互联网 发布:树莓派安装rpm软件 编辑:程序博客网 时间:2024/06/05 10:44
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将动画效果兼容至Android4.0
一、页面过渡兼容库的使用
使用这个兼容库也很简单,首先,在要控制跳转的页面调用TransitionController.getInstance().startActivity
方法来实现跳转,在其中主要是传入当前界面要过渡到另一页面的过渡元素View,以及另一个页面对应共享元素的View id值。
然后,在跳转到的第二个页面调用TransitionController.getInstance().show
方法来实现元素的过渡,传入参数也很简单。
最后呢,在页面返回的时候,调用TransitionController.getInstance().exitActivity
方法即可。
这样一个完整的界面过渡动画基本就可以使用了,当然,为了让实现的效果更炫酷,加入了对过渡动画状态的监听,可以在动画结束时加入自己的操作,为方便起见,兼容库包含圆形元素过渡:调用ViewAnimationCompatUtils.createCircularReveal
方法既可实现元素以圆形展开和收起,使用方式和ViewAnimationUtils类一致,以及矩形元素过渡:调用:ViewAnimationCompatUtils.createRectReveal
方法既可实现元素以矩形方式以左、上、右、下四个方向展开。
具体代码如下:
//参数一:当前Activity//参数二:跳转意图//参数三:当前页面跳转至下一页面的View//参数四:下一页面关联的View idTransitionController.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 animator) { } @Override public void onTransitionCancel(Animator animator) { } });//界面退出的时候调用TransitionController.getInstance().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、界面返回时将创建的父容器重新添加至下一个页面动画实现,将创建的元素以动画形式返回初始位置,结束后移除父容器
1、获取跳转页面过渡元素的位置
//rect 来存储共享元素位置信息Rect rect = new Rect();// 获取元素位置信息view.getGlobalVisibleRect(rect);
2、将跳转过渡元素的位置传给下一个页面
// 将位置信息附加到 intent 上intent.setSourceBounds(rect);intent.putExtra(TRANSITION_NEXT_ID, nextShowViewId);
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);
4、获取跳转到的页面元素截图并将其设为创建元素的背景
//获取跳转到的页面元素截图Bitmap cacheBitmap = BitmapUtil.getCacheBitmapFromView(next_view);//将其设为创建元素的背景virtalView.setBackgroundDrawable(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; }
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) { } }); }
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); } }
三、用兼容库将开源项目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);
,炫酷的登录页面就实现啦。
项目github地址:https://github.com/zhangke3016/TranslationCompat 欢迎star、fork。
- 实现Android5.0过渡动画兼容库
- android5.0之Activity过渡动画
- android5.0之Activity过渡动画
- android5.0适配——轻松实现acitivty跳转View无缝过渡动画
- android 页面过渡动画兼容库
- Android5.0Activity的转场动画、过渡动画、过场动画、跳转动画
- android5.x之Activity过渡动画
- [java]过渡动画实现
- android5.0 activity动画
- iOS 过渡动画的实现
- vue过渡动画实现原理
- Android5.0使用共享元素实现转场动画
- android5.0的过度动画
- Android5.0--Activity过度动画
- 实现图片左右旋转过渡动画
- FLIP 动画实现多维网格的过渡
- 用css3的transition实现过渡动画
- 动画过渡实现鼠标跟随导航效果
- wireshark抓包图解 TCP三次握手/四次挥手
- Eclipse下通过Maven的Jetty插件运行Web工程的配置,包括启动https
- MySQL执行计划解读
- codeforces733E LCA在线
- 单例模式的几种实现方式比较
- 实现Android5.0过渡动画兼容库
- Nov week1
- PMP学习笔记之第四章 项目整合管理
- STM32 USART寄存器方式编程
- ⑦基于时间型SQL盲注
- 【Codeforces 733F】 Drivers Dissatisfaction 【MST+bianry lifting】
- 关于Flux的学习
- jsp自定义标签
- 10种简单的Java性能优化