Android Canvas ScaleFocus 导致跳跃位置
Android Canvas ScaleFocus causing jumping position
我正在开发一款游戏,该游戏将俯视网格移动棋子(类似于国际象棋)。我希望用户能够平移和缩放地图。我一直在对矩阵进行转换,然后将这些更改连接到 canvas 矩阵。虽然它大部分都在工作,但我有一个奇怪的错误:
初始缩放后,如果我再次缩放,屏幕会跳跃(好像在其他地方滑动并立即移动到那里)然后平滑缩放。我已将此行为缩小到缩放函数的 scaleFocus 变量
canvas.scale(scaleFactor, scaleFactor, scaleFocusX, scaleFocusY);
如果我将 scaleFocusX 和 scaleFocusY 设置为 0,则始终使用原点作为缩放焦点并且不会发生跳跃。但是,当您滚动到离原点更远的地方时,使用原点是不切实际的。这是我的代码摘要。
public void onDraw(Canvas canvas) {
...
canvas.translate(-mPosX, -mPosY);
canvas.scale(scaleFactor, scaleFactor, scaleFocusX, scaleFocusY);
//Create an inverse of the tranformation matrix, to be used when determining click location.
canvas.getMatrix().invert(canvasMatrix);
... }
public class MyOnScaleGestureListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
scaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
scaleFactor = Math.max(MIN_SCALE, Math.min(scaleFactor, MAX_SCALE));
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
Point scaleFocus = calculateClickAbsoluteLocation
(detector.getFocusX(), detector.getFocusY());
scaleFocusX = scaleFocus.x;
scaleFocusY = scaleFocus.y;
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
//This method will take point on the phone screen, and convert it to be
//a point on the canvas (since the canvas area is larger than the screen).
public Point calculateClickAbsoluteLocation(float x, float y) {
Point result = new Point();
float[] coordinates = {x, y};
//MapPoints will essentially convert the click coordinates from "screen pixels" into
//"canvas pixels", so you can determine what tile was clicked.
canvasMatrix.mapPoints(coordinates);
result.set((int)coordinates[0], (int)coordinates[1]);
return result;
}
首先,而不是使用
float[] coordinates = {x, y};
你最好使用 PointF coordinates = new PointF(x, y);
,然后你可以用 coordinates.x
和 coordinates.y
.
得到 x
和 y
你的问题是当缩放时你仍然处理触摸事件(所以触摸被处理了两次)。
我们需要一个全局变量来告诉我们是否正在缩放:
boolean scaling = false
所以,在 OnTouchEvent 中你应该检查它:
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
detector.onTouchEvent(event);
if (detector.isInProgress())
scaling = true;
发布:
如果 (event.getAction() == MotionEvent.ACTION_UP) {
缩放=假;
onTouchEvent
中与点击相关的所有代码都应包含在
中
if (!scaling) { ... }
我正在开发一款游戏,该游戏将俯视网格移动棋子(类似于国际象棋)。我希望用户能够平移和缩放地图。我一直在对矩阵进行转换,然后将这些更改连接到 canvas 矩阵。虽然它大部分都在工作,但我有一个奇怪的错误:
初始缩放后,如果我再次缩放,屏幕会跳跃(好像在其他地方滑动并立即移动到那里)然后平滑缩放。我已将此行为缩小到缩放函数的 scaleFocus 变量
canvas.scale(scaleFactor, scaleFactor, scaleFocusX, scaleFocusY);
如果我将 scaleFocusX 和 scaleFocusY 设置为 0,则始终使用原点作为缩放焦点并且不会发生跳跃。但是,当您滚动到离原点更远的地方时,使用原点是不切实际的。这是我的代码摘要。
public void onDraw(Canvas canvas) {
...
canvas.translate(-mPosX, -mPosY);
canvas.scale(scaleFactor, scaleFactor, scaleFocusX, scaleFocusY);
//Create an inverse of the tranformation matrix, to be used when determining click location.
canvas.getMatrix().invert(canvasMatrix);
... }
public class MyOnScaleGestureListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
scaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
scaleFactor = Math.max(MIN_SCALE, Math.min(scaleFactor, MAX_SCALE));
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
Point scaleFocus = calculateClickAbsoluteLocation
(detector.getFocusX(), detector.getFocusY());
scaleFocusX = scaleFocus.x;
scaleFocusY = scaleFocus.y;
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
//This method will take point on the phone screen, and convert it to be
//a point on the canvas (since the canvas area is larger than the screen).
public Point calculateClickAbsoluteLocation(float x, float y) {
Point result = new Point();
float[] coordinates = {x, y};
//MapPoints will essentially convert the click coordinates from "screen pixels" into
//"canvas pixels", so you can determine what tile was clicked.
canvasMatrix.mapPoints(coordinates);
result.set((int)coordinates[0], (int)coordinates[1]);
return result;
}
首先,而不是使用
float[] coordinates = {x, y};
你最好使用 PointF coordinates = new PointF(x, y);
,然后你可以用 coordinates.x
和 coordinates.y
.
x
和 y
你的问题是当缩放时你仍然处理触摸事件(所以触摸被处理了两次)。
我们需要一个全局变量来告诉我们是否正在缩放:
boolean scaling = false
所以,在 OnTouchEvent 中你应该检查它:
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
detector.onTouchEvent(event);
if (detector.isInProgress())
scaling = true;
发布: 如果 (event.getAction() == MotionEvent.ACTION_UP) { 缩放=假;
onTouchEvent
中与点击相关的所有代码都应包含在
if (!scaling) { ... }