android 对多点触碰缩放imageview的大小,和手势滑动移动view位置的思考

最近公司要做一个手势滑动来缩放view的效果,因为以前没有遇到过这方面的知识,所以就在网上查了一下

这个效果的有2个问题:①多点触碰.②关于缩放后位置的摆放

第一个问题是比较好解决的,当第一个手指触碰屏幕是会触发down事件,当第二个手指,第三个手指。。。触碰屏幕是会触发pointer_down事件,滑动时会触发move事件,在move事件中可以通过event.getx(int pointindex)获得第index个点的相对于自身的距离,通过比较2次距离的大小来判断是放大还是缩小,关于这方面的资料网上很多,这里就不再累赘。

第二个问题我首先想到这和imageviwe的缩放很相似,通过查资料,关于iamgeview的缩放,有2中,第一继承imageviwe然后通过矩阵变换来实现,感觉不符合我的情况。第二种是通过继承View,然后通过ondraw(canvas) 中canvas.drawBitmap(bitmap   Rect Rect Paint);来绘制。

http://www.cnblogs.com/_ymw/p/4156577.html 通过参照这篇文章最终实现。

在这篇文章中,最主要的就是zoomimageview这个类,在这个类中使用到很多Obserable和Observer对象,这是使用了观察者模式,和我们的重点无关,先不管(这种编程模式还是很值得我们学习的,能更方便的重构代码,缺点是代码跳跃性增强)。


代码中AspectQuotient(看点商???) 这个类的含义不懂(以后再弄弄)但还好对我们的实现没什么影响,因为我们的内容的宽高比和父控件的宽高比一样

ZoomState是核心类,其中的Zoom是缩放的比例,mPanX,mPanY是空间中心左边的内容在全部内容中占的比例(为了理解这个含义我花了一天,说多了都是泪啊),还是没明白?看下图

mPanX的含义是x0/x1(当然关于相对点的选择是随意的,这篇博客是相对于控件的中心,而我实现是相对于控件左边界).mPanY类似
现在最主要的就是mPanX的计算问题,这里又有2种情况,
①:在滑动的情况下:当我们在控件上滑动dx的距离时,内容在放大的情况下也滑动了dx,所以mPanX=mPanX±dx/(zoom*contentWidth),这其中zoom是放大缩小的倍数,contentWidth是内容的原始大小。(见BasicZoomListener,和BasicZoomControl类中的pan(dx,dy)方法)
②:在实现缩放是mPanX的大小变化,我们可以知道当我们的缩放中心为我们选择的相对点时(这里为控件的中点),mPanx的大小是不变的.然而当我们的缩放中心是任意一点时呢?当我们的缩放中心是屏幕的1/4时,在缩放之前,1/4点的mPanX值为mPanx-(1/2-1/4)/zoom1,由前面可知,缩放后1/4点的mPanX值也是mPanx-(1/2-1/4)/zoom1,而这时中心的mPanX值为mPanx-(1/2-1/4)/zoom1+(1/2-1/4)/zoom2(zoom1为缩放之前的缩放倍数,zoom2为缩放之后的缩放倍数).这样我们就算出了缩放后的中心点的mPanX值,推广到一半的情况为mPanX=mPanX-(0.5-x)((1/zoom1)-(1/zoom2))(见BasicZoomControl类中的zoom(float,float,float)方法),推广到更一般的情况为mPanX=mPanX-(center-x)((1/zoom1)-(1/zoom2)),center为选择的相对点,x为缩放中心,mPanY的情况类似。
现在我们知道zoom和mPanX,mPanY的值,现在我们可以很轻松的算出缩放后图片的那一部分内容要显示在控件中了。
left=mPanX*zoom*contentWidth-contentWidth/2;
right=left+contentWidth;

 
  
 
  
 
  

今天在使用的时候发生了一个多点触碰时的bug,在这里补充一下。

在上面的文章中获得最后一个点的x和y的位置写法是float x=event.get(event.getpointerId(count-1));这种说法是错误的。

见 :http://stackoverflow.com/questions/6919292/pointerindex-out-of-range-android-multitouch

Example:

Touch 1 Down.

Touch 1 State Index=0. ID=0
Touch 1 State Index=0. ID=0
Touch 2 State Index=1. ID=1
Touch 2 State Index=0. ID=1

Touch 2 Down.

Touch 1 Release.

在第三次状态的时刻.event.getpointerId(count-1)得到的数值1,然而event.get(index)传的数值是index,这个时候第二个点id为1,index为0。event.get(1)就会报错java.lang.IllegalArgumentException: pointerIndex out of range。

解决方法为这里直接传count-1;







你可能感兴趣的:(android 对多点触碰缩放imageview的大小,和手势滑动移动view位置的思考)