可以看到,当触发 down 或者触发 up,cancel 时,如果之前处于缩放计算的状态,会将其状态重置, 并调用 onScaleEnd 方法 。
计算中心点:
final boolean configChanged = action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN || anchoredScaleCancelled;// 注意这里 final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP;final int skipIndex = pointerUp ? event.getActionIndex() : -1;// 确定焦点 float sumX = 0, sumY = 0; final int div = pointerUp ? count - 1 : count;final float focusX;final float focusY; if (inAnchoredScaleMode()) {// 在锚定比例模式下,焦点始终是双击或按钮按下时手势开始的位置 focusX = mAnchoredScaleStartX;focusY = mAnchoredScaleStartY;if (event.getY() < focusY) { mEventBeforeOrAboveStartingGestureEvent = true; } else {mEventBeforeOrAboveStartingGestureEvent = false;} } else { // 注意这里, 最终计算得到焦点for (int i = 0; i < count; i++) { if (skipIndex == i) continue; sumX += event.getX(i); sumY += event.getY(i); } focusX = sumX / div;focusY = sumY / div; } 3.2 计算缩放比例
计算缩放比例也很简单,就是计算各个手指到焦点的平均距离,在用户手指移动后用新的平均距离除以旧的平均距离,并以此计算得出缩放比例 。
// 计算到焦点的平均距离 floatdevSumX=0,devSumY=0; for(inti=0;i<count;i++){ if (skipIndex == i) continue; devSumX+=Math.abs(event.getX(i)-focusX); devSumY+=Math.abs(event.getY(i)-focusY); } finalfloatdevX=devSumX/div; finalfloatdevY=devSumY/div; // 注意这里 finalfloatspanX=devX*2; finalfloatspanY=devY*2; finalfloatspan; if(inAnchoredScaleMode()){ span=spanY; }else{ // 相当于 sqrt(x*x + y*y) span=(float)Math.hypot(spanX,spanY); }当用户移动的距离超过一定数值(数值大小由系统定义)后,会触发 onScaleBegin 方法,如果用户在 onScaleBegin 方法里面返回了 true,表示接受事件后,就会重置缩放相关数值,并且开始积累缩放因子 。
// mSpanSlop 和 mMinSpan 都是从系统里面取得的预定义数值,该数值实际上影响的是缩放的灵敏度 。// 不过该参数并没有提供设置的方法,如果对灵敏度不满意的话,和通过直接之际复制一个 ScaleGestureDetector 到项目中, 并且修改其中的数值 。finalintminSpan=inAnchoredScaleMode()?mSpanSlop:mMinSpan; if(!mInProgress&&span>=minSpan&& (wasInProgress||Math.abs(span-mInitialSpan)>mSpanSlop)){ mPrevSpanX=mCurrSpanX=spanX; mPrevSpanY=mCurrSpanY=spanY; mPrevSpan=mCurrSpan=span; mPrevTime=mCurrTime; mInProgress=mListener.onScaleBegin(this); }通知用户缩放:
if(action==MotionEvent.ACTION_MOVE{ mCurrSpanX=spanX; mCurrSpanY=spanY; mCurrSpan=span; booleanupdatePrev=true; if(mInProgress){ // 注意这里,用户的返回值决定了是否重新计算缩放因子 updatePrev=mListener.onScale(this); } // 如果用户返回了 true ,就会重新计算缩放因子 if(updatePrev){ mPrevSpanX=mCurrSpanX; mPrevSpanY=mCurrSpanY; mPrevSpan=mCurrSpan; mPrevTime=mCurrTime; } }由于缩放手势检测确实比较简单,也大概就这么多了,感兴趣的话,可以私信我
推荐阅读
- 自动识别 Android 不合理的内存分配
- Android面试题集锦之 Service
- 怎样搭高质量的Android项目框架,框架的结构具体描述?
- 谷歌Android 12L的适配机型,看得我们有点懵
- 浅谈Android类加载器
- Android 12推出正式版!这次的升级到底值不值得更新呢?
- 微软|来自X86的反击!微软研发Android和Windows深度整合
- 盖碗茶正确的喝法图解盖碗茶杯喝茶正确手势
- Android注解--初探
- 关于Android系统启动,你需要知道这些步骤