自定义View 之 PhotoView – 照片查看器

效果图

QQ图片20210708222840.gif

所需实现功能

1.将图片放于正中,宽/高铺满
2.双击放大、缩小
3.放大缩小位置为双击的地方
4.放大时能左右滑动
5.左右滑动时有惯性
6.手势放大缩小(两手张大、合并)

实现

1.加载图片

获取bitmap
image.png
绘制bitmap
image.png
drawBitmap的入参为图片左上角
image.png
所以要将图片显示在正中间得 算出左手角(x,y)
image.png

因为图片有两种造型,横向的或者纵向的,所以最小时和放大时,宽高比不一样
image.png

横向、纵向得到,最小和最大时的纵横比。
XXX * OVER_SCALE_FACTOR是因为想放大时,更大一点,可以划,而不是铺满状态
image.png

这样就绘制出一张初始图了
image.png

1865212030A.jpg

2. 双击放大、缩小

双击事件不要自己处理,GestureDetector 帮我们做好了

image.png

extends GestureDetector.SimpleOnGestureListener,里面有双击、滚动、单击、惯性等很多手势事件

image.png

重写onDoubleTap -双击
image.png

属性动画的情况
image.png
image.png

onDraw里 canvas.scale设置缩放比例
image.png

为了放大的时候,能放大双击的点

image.png

上面的解释
offsetX = (e.getX() - getWidth() / 2f) - (e.getX() - getWidth() / 2f) * bigScale / smallScale;

image.png

D60414B67.jpg

3. 放大时候,上下左右移动图片

移动其实就是滚动,也就是onScroll
image.png

记录下偏移量,然后在onDraw里移动就行
image.png

4. 滑动的时候,为了更加丝滑,得处理 惯性fling

OverScroller实现弹性滑动、惯性滑动的辅助类,有边界回弹功能
image.png

overScroller.fling()设置惯性
image.png

上面int minX, int maxX, int minY, int maxY的分析。
image.png

这个方法指挥调用一次,不像move,但是我们需要惯性的时候,是平滑的划过去的,所以得需要动画。
postOnAnimation 延时线程动画

image.png

onTouchEvent 关联起来

这样做完,没有关联起来,是不会走这里面的事件的,得onTouchEvent 关联 起来。

image.png

手势放大、缩小(两指张开)

需要做手势放大、缩小,得用到 ScaleGestureDetector

image.png

比较简单,onScale执行中的时候,将缩放因子detector.getScaleFactor(),赋值到currentScale当前缩放比例上。

image.png

最后这个也需要onTouchEvent 关联起来,而且先处理手势,在处理双击

image.png

多指触控事件

事件就是MotionEvent对象

单指:

image.png

多指:
在单指的基础上,多了ACTION_POINT_DOWN 与 ACTION_POINT_UP

第一个手指按下去:ACTION_DOWN
第二个手指按下去:ACTION_POINT_DOWN
第三个手指按下去:ACTION_POINT_DOWN

第一个手指抬起:ACTION_POINT_UP
第二个手指抬起:ACTION_POINT_UP

最后一个手指抬起:ACTION_UP

差不多就是这样。

使用

单指的时候,onTouchEvent里使用event.getAction()
image.png

多指的情况,onTouchEvent里使用event.getActionMasked()

image.png

Pointer的id与index
多个手指按下去,手机不会知道你到底是哪个手指按下去的,但是系统会维护一个列表。

手指按下:
依次类推,id是手指的id(永远不会变),index可以看做list的下标
image.png

当1号位置的手指抬起(第二个按下的手指抬起)
抬起的位置处,后面的手指list向前移动,但是id不会变,index都-1
image.png

如果有一个空位(之前按下又抬起了),现在在按下一个点位
系统不会管你是不是同一个手指,他不知道,都给当成那个手指
此时按下的手指id=1,然后列表后面整体向后移,index+1

image.png

具体代码:
多指处理就是处理,id和index。
image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享