[英]How to calculate coordinates of scaled canvas in Android
I am working with Android project. 我正在使用Android项目。 I have trouble with understand how to use ScaleDetector and Canvas.
我无法理解如何使用ScaleDetector和Canvas。
I have list called printTable with Rectangles. 我有一个名为带有矩形的printTable的列表。 I draw every Rectangle on screen in method onDraw().
我在屏幕上使用onDraw()方法绘制每个Rectangle。 Then I have second list called listPointer with Rectangles and id's of Rectangles.
然后,我有了第二个名为listPointer的列表,其中包含Rectangles和ID为Rectangles的列表。 I am checking that list onTouchEvent for rectangle that is draw on screen.
我正在检查屏幕上绘制的矩形的onTouchEvent列表。 If Rectangle contains X,YI print information about id of clicked Rectangle.
如果Rectangle包含X,YI将输出有关单击的Rectangle的ID的信息。
The problem is how to calculate my X,Y when I move my canvas or scale it? 问题是当我移动画布或缩放画布时如何计算X,Y?
public class Painter extends View {
//
private static final int INVALID_POINTER_ID = -1;
private float mPosX;
private float mPosY;
private float mLastTouchX;
private float mLastTouchY;
private int mActivePointerId = INVALID_POINTER_ID;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
//
Paint paint = new Paint();
List<Table> printTable = new ArrayList<Table>(); // lista wyświetlanych stolików
//
List<Pointer> listPointer = new ArrayList<Pointer>();
//
public Painter(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public Painter(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f));
invalidate();
return true;
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = ev.getPointerId(0);
for(int i = 0; i<listPointer.size(); i++)
{
if(listPointer.get(i).getRectangle().contains((int)(Math.round(x)), (int)(Math.round(y))))
{
if(listPointer.get(i).getIsItTable())
{
Log.e("Exc", "Stolik "+listPointer.get(i).getId());
}
else
{
Log.e("Exc", "Button "+listPointer.get(i).getId());
}
}
}
break;
}
case MotionEvent.ACTION_MOVE: {
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
// Only move if the ScaleGestureDetector isn't processing a gesture.
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
mPosX += dx;
mPosY += dy;
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_UP: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
case MotionEvent.ACTION_POINTER_UP: {
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
final int pointerId = ev.getPointerId(pointerIndex);
if (pointerId == mActivePointerId) {
// This was our active pointer going up. Choose a new
// active pointer and adjust accordingly.
final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
mLastTouchX = ev.getX(newPointerIndex);
mLastTouchY = ev.getY(newPointerIndex);
mActivePointerId = ev.getPointerId(newPointerIndex);
}
break;
}
}
return true;
}
//
public Painter(Context context) {
this(context, null, 0);
paint.setColor(Color.BLACK);
List<Table> printTable = Bridge.getTables(getContext());
}
@SuppressLint("DrawAllocation")
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Rect rect = null;
RectF rectF = null;
// czyszczenie tablicy
listPointer.clear();
for(int j = 0; j<printTable.size(); j++)
{
Table item = printTable.get(j);
// Obsługa rozciągania
canvas.save();
Log.d("DEBUG", "X: "+mPosX+" Y: "+mPosY);
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
// dodaje do tablicy stołów
paint.setColor(getResources().getColor(R.color.green));
rect = new Rect(item.getX1(), item.getY1(), item.getX2(), item.getY2());
rectF = new RectF(rect);
canvas.drawRoundRect(rectF, 0,0, paint);
listPointer.add(new Pointer(rect, true, j));
canvas.restore();
}
}
Get the matrix for the view. 获取视图的矩阵。 That should have all of the scaling and translating in it.
那应该包含所有缩放和平移。 Then multiply your x,y coordinates as a vector by the matrix used to scale the view.
然后将x,y坐标作为向量乘以用于缩放视图的矩阵。 That should convert prescaled/pretranslated coordinates into scaled coordinates.
那应该将预缩放/预转换的坐标转换为缩放坐标。 If it would require fewer multiplies, you can also multiply the post-scale coordiantes by the inverse of that matrix to get prescale coordinates.
如果需要较少的乘法,则还可以将后缩放坐标与该矩阵的逆值相乘,以获得预缩放坐标。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.