动画Android 进阶之旅

Android 进阶学习(二十七) 仿朋友圈查看图片动画

2021-07-02  本文已影响0人  Tsm_2020

先看一下实现效果


GIF 2021-7-2 11-05-12.gif

想要实现上面图片中放大图片的效果,我们大致可以分为三个过程

1.收集RecyclerView中所有View的在屏幕中的位置,以及宽高

2.将Activity变为透明

3.实现图片的放大和位置调整

1.在学习RecyclerView的LayoutManger 的过程中我们知道屏幕上面的item都在他的自身的一级缓存中,那么我们只需要遍历一级缓存,并找到他的position, 得到View 的pisition 后,剩下就比较简单了,首先我们需要一个封装类来承载我们所需要收集的信息

public class ImageScanAnimBean implements Serializable {
  private int startX;//开始横坐标
  private int startY;//开始纵坐标
  private int width;//宽度
  private int height;//高度
  private int position;//位置
}

封装类有了剩下的就是收集所需要的信息,为了动画做准备

  @JvmStatic
  fun getLocation(recycler_view:RecyclerView):ArrayList<ImageScanAnimBean>? {
      val manager = recycler_view.getLayoutManager()!!
      val count = manager.childCount//getChildCount 就是获取一级缓存
      val animBeans = ArrayList<ImageScanAnimBean>()
      for (m in 0 until count) {
          val child = manager.getChildAt(m)//遍历一级缓存
          val i = manager.getPosition(child!!)//获取一级缓存在RecyclerView 中的位置
          val location_index = IntArray(2)
          child!!.getLocationOnScreen(location_index)//获取View 在屏幕中的位置,
          val bean = ImageScanAnimBean()
          bean.startX = location_index[0]
          bean.startY = location_index[1]
          bean.width = child!!.width//获取View 的宽
          bean.height = child!!.height//获取View 的高
          bean.position = i
          animBeans.add(bean)
      }
      return animBeans
  }

2.从图片中可以看到,想要实现图片缩放效果,就必须让Activity实现透明的效果,最开始我的想法是使用反射,将Activity变为透明,但是试验后发现Activity变为透明需要一个过程,这无疑影响了动画的效果,这就必须使用Theme来解决这个问题了,但是使用Theme我还在担心一个问题,由于使用了沉浸式状态栏,所以Activity使用的Theme的必须是AppCompat系列了,但是想要让Activity透明就要使用@android:style/Theme.Translucent.NoTitleBar这个Theme ,我怕使用的时候存在不兼容的情况,但是实际情况是可以的,我就放心了,解决了透明问题,我们还要考虑另外一个问题,那就是给Activity 设置一个动画,这个动画什么都不需要执行,但是他的动画时间必须是我们放大图片的动画时间,这样能让我们的动画执行起来更加放心

3.有了所有View 的坐标,同时Activity都变为了透明的效果,那么想要实现我们最终的效果就比较简单了,无非就是修改margin 和宽高的过程,

  @JvmStatic
  fun openAnim(activity: Activity, imageView: View, bean: ImageScanAnimBean,after:()->kotlin.Unit){
  /// 先把View 按照传递过来的大小调整
      var params : CoordinatorLayout.LayoutParams =CoordinatorLayout.LayoutParams(bean.width,bean.height)
      params.leftMargin=bean.startX
      params.topMargin=bean.startY
      imageView.layoutParams=params

      ///执行动画,  margin的横坐标是从 传递过来的x ->0  , 纵坐标是传递过来的y ->0 , 宽高则是由原来的宽高变为屏幕的宽高

      val animator = ValueAnimator.ofFloat(1f,0f)
      animator.duration = 400
      animator.interpolator = AccelerateInterpolator()
      var screenWidth=ScreenUtils.getScreenWidth(activity)
      var screenHeight=ScreenUtils.getScreenHeight(activity)
      animator.addUpdateListener { valueAnimator: ValueAnimator ->
          val value = valueAnimator.animatedValue as Float
          var p : CoordinatorLayout.LayoutParams = imageView.layoutParams as CoordinatorLayout.LayoutParams
          p.leftMargin= ((bean.startX)*value).toInt()
          p.topMargin=((bean.startY)*value).toInt()
          p.width=(bean.width+((screenWidth-bean.width )*(1f-value)).toInt())
          p.height=(bean.height+((screenHeight-bean.height )*(1f-value)).toInt())
          imageView.layoutParams=p
      }
      animator.addListener(object : Animator.AnimatorListener {
          override fun onAnimationStart(animation: Animator) {}
          override fun onAnimationEnd(animation: Animator) {
              after()
          }
          override fun onAnimationCancel(animation: Animator) {}
          override fun onAnimationRepeat(animation: Animator) {}
      })
      animator.start()
  }

关闭动画

 @JvmStatic
  fun closeAnim(activity: Activity, imageView: View, bean: ImageScanAnimBean){
      val animator = ValueAnimator.ofFloat(0f,1f)
      animator.duration = 400
      animator.interpolator = AccelerateInterpolator()
      var screenWidth= ScreenUtils.getScreenWidth(activity)
      var screenHeight= ScreenUtils.getScreenHeight(activity)
      animator.addUpdateListener { valueAnimator: ValueAnimator ->
          val value = valueAnimator.animatedValue as Float
          var p : CoordinatorLayout.LayoutParams = imageView.layoutParams as CoordinatorLayout.LayoutParams
          p.leftMargin= ((bean.startX)*value).toInt()
          p.topMargin=((bean.startY)*value).toInt()
          p.width=screenWidth- (((screenWidth-bean.width))*value).toInt()
          p.height=screenHeight-(((screenHeight-bean.height))*value).toInt()

          imageView.layoutParams=p
      }
      animator.start()
      animator.addListener(object : Animator.AnimatorListener {
          override fun onAnimationStart(animation: Animator) {}
          override fun onAnimationEnd(animation: Animator) {
              activity.finish()
              //发现如果先关闭activity,图片缩放可能受到影响,导致中间状态消失,所以这里结束的时候执行一个非常短的动画
              activity.overridePendingTransition(R.anim.serviceui_image_scan_in_0, R.anim.serviceui_image_scan_out_0)
          }
          override fun onAnimationCancel(animation: Animator) {}
          override fun onAnimationRepeat(animation: Animator) {}
      })
  }
上一篇 下一篇

猜你喜欢

热点阅读