首页 技术 正文
技术 2022年11月10日
0 收藏 568 点赞 4,080 浏览 3803 个字

最近在实现一个类似淘宝中的评论列表的功能,其中要在列表中显示评论图,点击图片后显示大图进行查看,各家app几乎都会有这样的功能。

支持缩放的fresco图片控件 —— fresco sample: ZoomableDraweeView

可以看到,一个体验较好的查看大图的基本功能有,

第一,左右滑动时切换图片;

第二,双击或双指缩放实现图片的缩放;

第三,图片放大时,滑动到边缘继续滑动时,切换图片。

因为我们的app中使用了fresco库,但fresco提供的SimpleDraweeView不支持缩放,看网上有人扩展了SimpleDraweeView,使之支持缩放。但经过漫长的调研,发现fresco近期提供了一个新的sample:ZoomableDraweeView,专门用来支持缩放,欣喜若狂的下载下来把玩了一把,发现三个需求点都满足!可惜的是,这个控件在细节上有几点不满足:双击后放大到最大,再双击后却缩小为最小(期望恢复为正常大小),虽然最小可以设置,但这个值应该是在双指缩小时才用到。另一点是在双指缩小并松开后,图片保持在那个缩小的尺寸(期望自动恢复为正常大小)。

查看代码后发现需要修改几点就可以满足我的需求。下面的内容主要记录我思考问题、解决问题的思路,如果你也有类似的需求,可以直接拿代码:https://github.com/ibosong/CommentGallery

1. 双击恢复正常尺寸

修改DoubleTapGestureListener 中的onDoubleTapEvent方法,因为主要修改的逻辑在双指松开后,于是我们在MotionEvent.ACTION_UP的case中修改相关逻辑。首先判断mDoubleTapScroll,即是否是双击后不松开并滑动的操作,这种操作下如果在松开手指时,图片为缩小状态,应当恢复正常大小,所以将原代码:

if (mDoubleTapScroll) {  float scale = calcScale(vp);  zc.zoomToPoint(scale, mDoubleTapImagePoint, mDoubleTapViewPoint);}

修改为:

if (mDoubleTapScroll) {    float scale = calcScale(vp);    if (scale < 1.0f) {        zc.zoomToPoint(1.0f, mDoubleTapImagePoint, mDoubleTapViewPoint,                DefaultZoomableController.LIMIT_ALL,                DURATION_MS,                null);    } else {        zc.zoomToPoint(scale, mDoubleTapImagePoint, mDoubleTapViewPoint);    }}

else里面的代码是正常双击后的代码,将其中的minScale 改为1.0f即可

else {    final float maxScale = zc.getMaxScaleFactor();    final float minScale = zc.getMinScaleFactor();    if (zc.getScaleFactor() < (maxScale + minScale) / 2) {        zc.zoomToPoint(                maxScale,                ip,                vp,                DefaultZoomableController.LIMIT_ALL,                DURATION_MS,                null);    } else {        zc.zoomToPoint(                /*minScale*/1.0f,                ip,                vp,                DefaultZoomableController.LIMIT_ALL,                DURATION_MS,                null);    }}

2. 双指缩放,处理双指缩小图片后松开手指的情况

阅读代码可知,ZoomableDraweeView中的onTouchEvent方法调用了DefaultZoomableController的onTouchEvent方法,这里面通过mGestureDetector的处理,最终回调到ZoomableDraweeView中的onGestureBegin,onGestureUpdate和onGestureEnd这三个方法中。mGestureDetector的处理是在MultiPointerGestureDetector的onTouchEvent方法中。这里面原来的按下和松开手指的逻辑是这样的:

case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_POINTER_DOWN:case MotionEvent.ACTION_POINTER_UP:case MotionEvent.ACTION_UP: {  // restart gesture whenever the number of pointers changes  mNewPointerCount = getPressedPointerCount(event);  stopGesture();  updatePointersOnTap(event);  if (mPointerCount > 0 && shouldStartGesture()) {    startGesture();  }  break;} 

每次在MotionEvent.ACTION_DOWN和MotionEvent.ACTION_UP情况下执行相同的动作:先stopGesture,然后startGesture,即先触发onGestureEnd,然后触发onGestureBegin。显然这样的处理是不合逻辑的,为什么在手指按下的时候要触发onGestureEnd?于是我们将代码修改为:

case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_POINTER_DOWN:    mNewPointerCount = getPressedPointerCount(event);    updatePointersOnTap(event);    if (mPointerCount > 0 && shouldStartGesture()) {        startGesture();    }    break;case MotionEvent.ACTION_POINTER_UP:case MotionEvent.ACTION_UP: {    mNewPointerCount = getPressedPointerCount(event);    updatePointersOnTap(event);    stopGesture();    break;}

在手指按下的时候触发onGestureBegin,手指抬起的时候触发onGestureEnd。这时候我们只要在DefaultZoomableController中的onGestureEnd方法中处理松开手指的情况:如果图片被缩小,则通过调用zoomToPoint方法将图片恢复正常大小。

@Overridepublic void onGestureEnd(TransformGestureDetector detector) {    FLog.v(TAG, "onGestureEnd");    // When the image was zoomed in, releasing the fingers will restore the size of image.    if (getScaleFactor() < 1.0f) {        zoomToPoint(1.0f, new PointF(0.f, 0.f), new PointF(0.f, 0.f));    }}

这里onGestureUpdate方法里的逻辑也要改一下,不要再调用mGestureDetector.restartGesture()。

@Overridepublic void onGestureUpdate(TransformGestureDetector detector) {     FLog.v(TAG, "onGestureUpdate");     boolean transformCorrected = calculateGestureTransform(mActiveTransform, LIMIT_ALL);     onTransformChanged();  // if (transformCorrected) {  // mGestureDetector.restartGesture();  // }   // A transformation happened, but was it without correction?  mWasTransformCorrected = transformCorrected;}

这样实现,操作起来比较生硬,恢复大小的时候没有动画。

支持缩放的fresco图片控件 —— fresco sample: ZoomableDraweeView

于是我们将onGestureEnd中的处理移至AbstractAnimatedZoomableController中,并将zoomToPoint修改为另一个实现了动画的重载的方法:

@Overridepublic void onGestureEnd(TransformGestureDetector detector) {    // When the image was zoomed in, releasing the fingers will restore the size of image.    if (getScaleFactor() < 1.0f) {        zoomToPoint(1.0f, new PointF(0.f, 0.f), new PointF(0.f, 0.f), LIMIT_ALL, 300, null);    }}

这样我们的改造就全部完成了,安装体验一下。

支持缩放的fresco图片控件 —— fresco sample: ZoomableDraweeView

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,487
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,903
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,736
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,486
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,126
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,289