gpt4 book ai didi

安卓。 Canvas 缩放和平移

转载 作者:太空宇宙 更新时间:2023-11-03 10:19:14 27 4
gpt4 key购买 nike

我创建了自定义 View ,您可以在其中触摸和缩放它。大部分工作都是在这个 post 的帮助下创建的

接下来我观察到,如果我想放大图像,它总是缩放到左上角。这是我的 onDraw() 方法:

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

canvas.save();
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);

// actual drawing

canvas.getClipBounds(mRect);
canvas.restore();
}

所以这是 canvas.scale(px, py); 的正常行为 我希望从我的角度缩放到中心点(稍后我将采用 focalXfocalY 坐标,但现在只是居中)。我决定更换

canvas.scale(mScaleFactor, mScaleFactor);

canvas.scale(mScaleFactor, mScaleFactor, getWidth()/2-mPosX, getHeight()/2-mPosY);

现在它在图像的中间完美缩放。但它会以某种方式影响我的 mPosX、mPosY 坐标。我附上一张图片以便更好地理解。

Top left corner is eqivalent mPosX = 0, mPosY=0

左上角等价的mPosX = 0, mPosY=0, 就OK了。

下一步如果我正在缩小接下来会发生:

enter image description here

现在它决定左上角等同于mPosX=0,mPosY=0(左上角)。但按照我的逻辑,它应该有点像 (mPosX=100, mPosY=130) 或类似的东西。

所以我的问题是我正在从我的实际内容 View 中滑出。我应该怎么做才能防止这种行为?

最佳答案

关于接触点计算和引用我有同样的问题 this answer ,我使用指标以自己的方式解决了它。以上答案提供了更好的缩放和拖动功能,但没有正确的触摸点。这是完整的代码并忽略我自己的变量。

package axis.nbapp;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import java.io.IOException;

public class NewView extends ViewGroup {
float dx;
float dy;
float scaleFac;

Region r;
private Path mPath;
private Paint mPaint;
private Path mTransformedPath;
Stencil stencil;
private Paint cColor;
boolean scaling;
Canvas bmcanvas;
SVG svg = null;
int viewWidth;
int viewHeight;
float svgWidth;
float svgHeight;

// States.
private static final byte NONE = 0;
private static final byte DRAG = 1;
private static final byte ZOOM = 2;

private byte mode = NONE;

// Matrices used to move and zoom image.
private Matrix matrix = new Matrix();
private Matrix matrixInverse = new Matrix();
private Matrix savedMatrix = new Matrix();


// Parameters for zooming.
private PointF start = new PointF();
private PointF mid = new PointF();
private float oldDist = 1f;
private float[] lastEvent = null;
private long lastDownTime = 0l;

private float[] mDispatchTouchEventWorkingArray = new float[2];
private float[] mOnTouchEventWorkingArray = new float[2];


@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
mDispatchTouchEventWorkingArray[0] = ev.getX();
mDispatchTouchEventWorkingArray[1] = ev.getY();
mDispatchTouchEventWorkingArray = screenPointsToScaledPoints(mDispatchTouchEventWorkingArray);
ev.setLocation(mDispatchTouchEventWorkingArray[0], mDispatchTouchEventWorkingArray[1]);
return super.dispatchTouchEvent(ev);
}

public NewView(Context context) {
super(context);
init(context);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);


}

public NewView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

public NewView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}


private void init(Context context) {

}


/**
* Determine the space between the first two fingers
*/
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}

/**
* Calculate the mid point of the first two fingers
*/
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}

private float[] scaledPointsToScreenPoints(float[] a) {
matrix.mapPoints(a);
return a;
}

private float[] screenPointsToScaledPoints(float[] a) {
matrixInverse.mapPoints(a);
return a;
}


@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
}
}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() != GONE) {
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
}
}

@Override
protected void dispatchDraw(Canvas canvas) {
float[] values = new float[9];
matrix.getValues(values);
canvas.save();
canvas.translate(values[Matrix.MTRANS_X], values[Matrix.MTRANS_Y]);
canvas.scale(values[Matrix.MSCALE_X], values[Matrix.MSCALE_Y]);



super.dispatchDraw(canvas);
canvas.restore();
}

@Override
public boolean onTouchEvent(MotionEvent event) {

// handle touch events here
mOnTouchEventWorkingArray[0] = event.getX();
mOnTouchEventWorkingArray[1] = event.getY();

mOnTouchEventWorkingArray = scaledPointsToScreenPoints(mOnTouchEventWorkingArray);

event.setLocation(mOnTouchEventWorkingArray[0], mOnTouchEventWorkingArray[1]);

switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
mode = DRAG;
lastEvent = null;
long downTime = event.getDownTime();
if (downTime - lastDownTime < 300l) {
float density = getResources().getDisplayMetrics().density;
if (Math.max(Math.abs(start.x - event.getX()), Math.abs(start.y - event.getY())) < 40.f * density) {
savedMatrix.set(matrix);
mid.set(event.getX(), event.getY());
mode = ZOOM;
lastEvent = new float[4];
lastEvent[0] = lastEvent[1] = event.getX();
lastEvent[2] = lastEvent[3] = event.getY();
}
lastDownTime = 0l;
} else {
lastDownTime = downTime;
}
start.set(event.getX(), event.getY());
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
}
lastEvent = new float[4];
lastEvent[0] = event.getX(0);
lastEvent[1] = event.getX(1);
lastEvent[2] = event.getY(0);
lastEvent[3] = event.getY(1);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
lastEvent = null;
break;
case MotionEvent.ACTION_MOVE:
final float density = getResources().getDisplayMetrics().density;
if (mode == DRAG) {
matrix.set(savedMatrix);
dx = event.getX() - start.x;
dy = event.getY() - start.y;
matrix.postTranslate(dx, dy);
matrix.invert(matrixInverse);
if (Math.max(Math.abs(start.x - event.getX()), Math.abs(start.y - event.getY())) > 20.f * density) {
lastDownTime = 0l;
}
} else if (mode == ZOOM) {
if (event.getPointerCount() > 1) {
float newDist = spacing(event);
if (newDist > 10f * density) {
matrix.set(savedMatrix);
float scale = (newDist / oldDist);
scaleFac = newDist;
matrix.postScale(scale, scale, mid.x, mid.y);
matrix.invert(matrixInverse);
}
} else {
matrix.set(savedMatrix);
float scale = event.getY() / start.y;
scaleFac = scale;
matrix.postScale(scale, scale, mid.x, mid.y);
matrix.invert(matrixInverse);
}
}

break;
}


float[] values = new float[9];
matrix.getValues(values);


//int x = ((int)(event.getX() - values[2]*values[Matrix.MSCALE_X]))/(int)values[0];
//int y = ((int)(event.getY() - values[5]*values[Matrix.MSCALE_Y]))/(int)values[4];

int x = ((int)(event.getX() / values[Matrix.MSCALE_X] - (values[Matrix.MTRANS_X]/values[Matrix.MSCALE_X])));
int y = ((int)(event.getY() / values[Matrix.MSCALE_Y] - (values[Matrix.MTRANS_Y]/values[Matrix.MSCALE_Y])));


invalidate();
return true;
}


}

检查 onTouchEvent 您可以通过以下计算找到转换后的 x、y 触摸点。

 int x = ((int)(event.getX() / values[Matrix.MSCALE_X] - (values[Matrix.MTRANS_X]/values[Matrix.MSCALE_X])));
int y = ((int)(event.getY() / values[Matrix.MSCALE_Y] - (values[Matrix.MTRANS_Y]/values[Matrix.MSCALE_Y])));

关于安卓。 Canvas 缩放和平移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27619854/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com