一、小红书缩放图片效果
效果:在列表上双指触摸某个ImageView后,可直接对其进行手势缩放的效果,并且缩放的View可全屏延伸至状态栏,相比先点击图片进入大图页再对图片进行双指缩放的流程更加直接高效。如下视频效果:
但通过以上视频可发现小红书一些异常交互问题:
1. 缩放中心不是触摸时两指中心,而是图片中心,达不到指哪缩哪的效果;
2. 松开双指,半透明背景没有随图片缩小而变透明,而是图片缩放到正常大小后突现变为透明;
3. 松开双指,图片缩放到正常大小时,(大概率)偶现突然变黑闪一下;
4. 双指缩放图片图片的过程中,背景下层还能触发触摸效果(如点底层头像会进个人页)。
5. 不能缩放视频或其他View
以上问题给小红书持续反馈了1年多一直没有得到解决,所以索性自己高仿一个,并且已经在公司数百万DAU的项目中上线验证过,有需要的可放心拿去用。
二、仿照的效果
1.双指触摸可指哪缩哪,缩放中心点为触摸时双指中心点,而非图片中心点;
2.支持缩放任何View(将要缩放的View放在TouchToScaleLayout即可);
3.松开双指,半透明背景随回弹动画逐渐变透明;
三、相关代码
Github链接:https://github.com/axkza/TouchToScaleLayout
APK地址:https://xkz-1252121784.cos.ap-chengdu.myqcloud.com/TouchToScaleLayout.apk
用法:在需要双指触摸缩放的View外层嵌套TouchToScaleLayout即可,布局如下:
四、实现思路
以上代码非常简单,下面就大概讲一下思路:
如何将列表中触摸到的View显示到列表的上层,并且可以拖动延伸到状态栏?
双指触摸该View时:
- 记录该View的宽高并通过getLocationOnScreen() 获取其相对屏幕顶点的top和left,用于确定View的位置;
- 将该View从父布局中removeView;
- new一个沉浸式的dialog,结合上面获取到的宽高和top、left,将该View addView到Dialog中显示;(也可addView到DecorView中,都是为了是能将该View平移的显示到原本UI的上层,并且可延伸到状态栏的效果)
如何实现指哪缩哪的效果?
1.双指触摸该View时:
- 记录【首次触摸时双指距离】、【首次触摸屏幕时两指中心点的x坐标】、【首次触摸屏幕时两指中心点的y坐标】
2.ACTION_MOVE时:
计算以下数值,用于缩放和位移,达到指哪缩哪的效果:
- 缩放比 = (当前双指距离 - 首次触摸时双指距离) / 首次触摸时双指距离
- 缩放中心点 (0,0)
- leftMargin = 当前两指中心点的x坐标 - 首次触摸屏幕时两指中心点的x坐标 * 缩放比 + 首次触摸时的原始leftMargin
- topMargin = 当前两指中心点的y坐标 - 首次触摸屏幕时两指中心点的y坐标 * 缩放比 + 首次触摸时的原始leftMargin
双指触摸后,如何解决和父控件滑动冲突的问题?
- 双指触摸该View时,调用requestDisallowInterceptTouchEvent(true)屏蔽父布局的事件拦截;
- 手指抬起时,调用requestDisallowInterceptTouchEvent(false)恢复父布局的事件拦截