我在这个问题上被困了八个小时,所以我想是时候寻求帮助了。
在我开始我的问题之前,我会告诉大家我已经浏览过这个网站和谷歌,但我找到的答案都没有帮助。(这是一个,另一个,另一个。)
事情是这样的:我有一个扩展SurfaceView
(我们称之为MySurface
)并覆盖其中的许多方法的类。通常,它会绘制几个正方形和文本框,这一切都很好。一旦用户开始触摸,它就会转换为 a Bitmap
,然后绘制每一帧,直到用户释放。
问题是:我想实现这样一个功能,用户可以将两根手指放在屏幕上,捏合缩放,也可以平移(但只能用两根手指向下)。
我找到了一些捏到缩放的实现,并通过以下方法将它们调整到我的Canvas
对象中MySurface
:
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.scale(mScaleVector.z, mScaleVector.z); // This is the scale factor as seen below
canvas.translate(mScaleVector.x, mScaleVector.y); // These are offset values from 0,0, both working fine
// Start draw code
// ...
// End draw code
canvas.restore();
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float factor = detector.getScaleFactor();
if (Math.abs(factor - 1.0f) >= 0.0075f) {
mScaleVector.z *= factor;
mScaleVector.z = Math.max(MIN_ZOOM, Math.min(mScaleVector.z, MAX_ZOOM));
}
// ...
invalidate();
return true;
}
}
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
if (event.getPointerCount() == 2) {
if (action == MotionEvent.ACTION_POINTER_DOWN && pointerIndex == 1) {
// The various pivot coordinate codes would belong here
}
}
detector.onTouchEvent(event); // Calls the Scale Gesture Detector
return true;
}
虽然这两个元素都可以正常工作——来回滚动和捏拉缩放——但存在一个大问题。捏合缩放在使用时会放大到点0,0
,而不是放大到手指点。
我尝试了很多方法来解决这个问题:
- 使用
canvas.scale(mScaleVector.z, mScaleVector.z, mScaleVector.x, mScaleVector.y);
; 显然,这会产生不需要的结果,因为mScaleVector
x 和 y 值是 0 偏移量。 - 管理使用与方法相同的偏移量的“枢轴”坐标
translate()
,但这会产生相同的0,0
问题,或者在触摸视图时跳转。 - 许多其他事情......我已经对上述枢轴坐标做了很多工作,试图将其位置基于用户的第一次触摸,并相对于每个连续手势的触摸移动它。
此外,这个画布必须是有界的,所以用户不能永远滚动。但是,当我使用该.scale(sx, sy, px, py)
方法时,它会将事情推到我设置的任何范围之外.translate()
。
我……在这一点上对任何事情都持开放态度。我知道可以添加此功能,就像在 Android 4.0 库中看到的那样(查看单个图像时)。我试图追踪处理此问题的源代码,但无济于事。