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.的更多相关文章

  1. css3 transition animation nick

    时光转眼即逝,又到周六了,今天写点某部分人看不起的css玩玩! 转换 转换属性transform: 浏览器前缀: -webkit-transform;-o-transform;-moz-transfo ...

  2. Atitti css transition Animation differ区别

    Atitti  css   transition Animation differ区别 1.1. transition的优点在于简单易用,但是它有几个很大的局限.  1 1.2. Transition ...

  3. Atitti  css   transition Animation differ区别

    Atitti  css   transition Animation differ区别 1.1. transition的优点在于简单易用,但是它有几个很大的局限.  1 1.2. js 动态改变 st ...

  4. css3动画transition animation

    CSS动画简介  transition   animation transition过渡:css3通过transitions属性引入时间概念,通过开始.结束状态自动计算中间状态,实现状态改变的过渡效果 ...

  5. ..\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 ...

  6. CSS3 & transition & animation

    CSS3 & transition & animation https://developer.mozilla.org/en-US/docs/Web/CSS/transition-ti ...

  7. CSS动画-transition/animation

    HTML系列: 人人都懂的HTML基础知识-HTML教程(1) HTML元素大全(1) HTML元素大全(2)-表单 CSS系列: CSS基础知识筑基 常用CSS样式属性 CSS选择器大全48式 CS ...

  8. CSS Transform / Transition / Animation 属性的区别

    back21 Jun 2011 Category: tech Tags: css 最近想UI的动画转到css3能吃进3d加速的属性上面来以加强动画的连贯性.只是对于css几个新加的属性不太熟悉,常常容 ...

  9. css3的新特性transform,transition,animation

    一.transform css3引入了一些可以对网页元素进行变换的属性,比如旋转,缩放,移动,或者沿着水平或者垂直方向扭曲(斜切变换)等等.这些的基础都是transform属性 transform属性 ...

随机推荐

  1. java使用batik转换svg文件

    svg是一种矢量图片格式,用来保存高保真的图片.我们可以用编辑器打开svg,我们可以看到svg文件其实就是一个xml文件,这种文件浏览器也可以识别.因此要查看svg用现成的浏览器就可以了.值得庆幸的是 ...

  2. BFS+状态压缩 hdu-1885-Key Task

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1885 题目意思: 给一个矩阵,给一个起点多个终点,有些点有墙不能通过,有些点的位置有门,需要拿到相应 ...

  3. js模板引擎实现原理

    将html模板放入script标签中 // "> // ]]> 使用javascript开始解析模板 // )[^\t]*)'/g,"$1\r"). repl ...

  4. Android TextView中有图片有文字混合排列

    Android TextView中有图片有文字混合排列 1.使用html.fromHtml 2.新建ImageGetter 3.使用<img src>标签 demo: 1.设置文字 ((T ...

  5. oracle4

    分页查询 按雇员的id号升序取出 oracle的分页一共有三种方式 .根据rowid来分   ) ) order by cid desc; 执行时间0.03秒 .按分析函数来分   and rk> ...

  6. CentOS远程系统管理之VNC

    写这篇有摘自他人的地方,如若侵犯请立即告知,第一时间下降!! 现在比较好用的用的广泛的是SSH和PUTTY,通过这些客户端来管理LINUX服务器的,下面主要介绍另一款VNC软件,主要由两个部分组成:V ...

  7. (转载)myeclipse项目名称重命名

    myeclipse项目名称重命名 实例1 今天晚上在做一个jsp唱片显示的实例,myeclipse项目名称原本想写music结果写成了musci.这就需要项目名称的重命名,单纯的使用 “重构--> ...

  8. 也许是关于C#的一些常见误区

    写这点东西主要是看到知乎上有人在讨论相关的问题,但是有不少人都在说一些不严谨,甚至是完全错误 但是流传甚广的东西,甚至是一些大神都在说,以下根据我的回答总结.    一个很常见又很低级的误区是:认为引 ...

  9. 从源码角度深入理解Handler

    为了获得良好的用户体验,Android不允许开发者在UI线程中调用耗时操作,否则会报ANR异常,很多时候,比如我们要去网络请求数据,或者遍历本地文件夹都需要我们在新线程中来完成,新线程中不能更新UI, ...

  10. Android(java)学习笔记185:xml文件生成

    1.xml文件: 用元素描述数据,跨平台. 2.利用传统的方式创建xml文件,下面是一个案例: 设计思路:建立一个学生管理系统,创建xml文件保存学生信息: (1)首先是布局文件activity_ma ...