先看一下实现效果
想要实现上面图片中放大图片的效果,我们大致可以分为三个过程
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) {}
})
}