缩放手势 ScaleGestureDetector 源码解析,这一篇就够了 (3)

布尔类型量,标志着一个操作的完成或者结束(手指离开,手指按下)

final boolean configChanged = action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN || anchoredScaleCancelled; pointerUp

布尔类型量,用于判断当前动作,是否为手指离开(抬起动作)

final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP; skipIndex

标记量,在是手指离开的情况下,标记离开手指

在后面计算新的焦点代码中,跳过该手指的标记点坐标,进行计算

final int skipIndex = pointerUp ? event.getActionIndex() : -1; 初始化计算所需临时变量 // Determine focal point float sumX = 0, sumY = 0; // 如果是抬起手指,则当前手指数减1,否则不变 final int div = pointerUp ? count - 1 : count; final float focusX; final float focusY; 判断是否为锚定比例模式

是的话直接将点击时记下的点,作为焦点

不是的话,把所有点累加求和,除以总个数,计算平均值

if (inAnchoredScaleMode()) { // In anchored scale mode, the focal pt is always where the double tap // or button down gesture started // 在锚定比例模式中,焦点pt始终是双击的位置,或按下手势开始 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; } 算缩放比例

计算缩放比例也很简单,就是计算各个手指到焦点的平均距离,在用户手指移动后用新的平均距离除以旧的平均距离,并以此计算得出缩放比例。

// Determine average deviation from focal point @Google translate float devSumX = 0, devSumY = 0; for (int i = 0; i < count; i++) { if (skipIndex == i) continue; // Convert the resulting diameter into a radius. devSumX += Math.abs(event.getX(i) - focusX); devSumY += Math.abs(event.getY(i) - focusY); } final float devX = devSumX / div; final float devY = devSumY / div; // Span is the average distance between touch points through the focal point; // i.e. the diameter of the circle with a radius of the average deviation from // the focal point. final float spanX = devX * 2; final float spanY = devY * 2; final float span; if (inAnchoredScaleMode()) { span = spanY; } else { span = (float) Math.hypot(spanX, spanY); } 计算平均偏差

确定焦点的平均偏差

float devSumX = 0, devSumY = 0; for (int i = 0; i < count; i++) { if (skipIndex == i) continue; // Convert the resulting diameter into a radius. devSumX += Math.abs(event.getX(i) - focusX); devSumY += Math.abs(event.getY(i) - focusY); } final float devX = devSumX / div; final float devY = devSumY / div; 计算缩放比例

跨度是通过焦点的触摸点之间的平均距离;

即圆的直径,其半径为平均偏差

这里的 Math.hypot(spanX, spanY) 方法,相当于 sqrt(xx + yy)

final float spanX = devX * 2; final float spanY = devY * 2; final float span; if (inAnchoredScaleMode()) { span = spanY; } else { span = (float) Math.hypot(spanX, spanY); } 结束缩放事件

@Google Translate:根据需要调度开始/结束事件。

如果配置发生更改,请通过开始通知应用重置其当前状态

一个新的比例事件流。

这里就不做太多描述,主要就是:

判断是不是所有手指都离开了屏幕

如果是,那么索命这个缩放进程结束了

则保存当前缩放的数据

调用 onScaleEnd 方法,结束当前操作

final boolean wasInProgress = mInProgress; mFocusX = focusX; mFocusY = focusY; if (!inAnchoredScaleMode() && mInProgress && (span < mMinSpan || configChanged)) { mListener.onScaleEnd(this); mInProgress = false; mInitialSpan = span; } if (configChanged) { mPrevSpanX = mCurrSpanX = spanX; mPrevSpanY = mCurrSpanY = spanY; mInitialSpan = mPrevSpan = mCurrSpan = span; } 触发 onScaleBegin 开始缩放

当手指移动的距离超过一定数值(数值大小由系统定义)后,会触发 onScaleBegin 方法

如果用户在 onScaleBegin 方法里面返回了 true,则接受事件后,就会重置缩放相关数值,并且开始积累缩放因子。

final int minSpan = 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); } 通知用户进行缩放处理

@ Google Translate: 处理动作;焦点和跨度/比例因子正在发生变化。

这块代码的功能主要就是通知用户(编程者)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjzfd.html