我已经移植了一些用于将图像视图缩放为 android 的单声道的 android 代码,但我在使用比例检测器焦点时遇到了问题。我需要以编程方式绘制对象,所以我重写了 ondraw 方法。
问题是,当我的缩放比例不是 1 时,如果我捏住绘制对象的一侧,绘制的对象会从捏合焦点跳开,你最终会得到一个焦点,而不是你开始的焦点(如果缩放比例大于 1)。如果缩放比例小于 1,则绘制的对象会跳向捏合焦点。
我几乎什么都试过了,但我一定是太老太累了,因为我就是想不通。
在 ondraw 中,我先缩放然后平移,然后在固定点绘制对象。
我是否以正确的方式处理这件事?我在搜索中找不到任何涉及在画布上的某个点绘制对象同时实现捏缩放的内容。
如果有人可以提供帮助,将不胜感激。
代码如下...
class clsTarget : ImageView, ImageView.IOnTouchListener
{
private ScaleGestureDetector mScaleDetector;
private ScaleListener sListener;
private static float mScaleFactor = 0.6F;
private static float scalePointX;
private static float scalePointY;
private static int INVALID_POINTER_ID = -1;
private int mActivePointerId = INVALID_POINTER_ID;
private static float mPosX, mPosY, mLastTouchX, mLastTouchY;
public clsTarget(Context context)
: base(context)
{
this.SetOnTouchListener(this);
sListener = new ScaleListener();
mScaleDetector = new ScaleGestureDetector(context, sListener);
mScaleFactor = 800F / (float)Math.Min(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels);
}
protected override void OnDraw(Android.Graphics.Canvas canvas)
{
canvas.Save();
canvas.Scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY);
canvas.Translate(mPosX, mPosY);
Paint p = new Paint(PaintFlags.AntiAlias);
p.Color = Color.Orange;
p.SetStyle(Paint.Style.Fill);
p.StrokeWidth = 1F;
canvas.DrawCircle(400, 400, 200, p);
canvas.Restore();
}
public bool OnTouch(View v, MotionEvent e)
{
mScaleDetector.OnTouchEvent(e);
switch (e.Action & MotionEventActions.Mask)
{
case MotionEventActions.Down:
float x = (e.GetX() - scalePointX) / mScaleFactor;
float y = (e.GetY() - scalePointY) / mScaleFactor;
mLastTouchX = x;
mLastTouchY = y;
mActivePointerId = e.GetPointerId(0);
break;
case MotionEventActions.Move:
int pointerIndex = e.FindPointerIndex(mActivePointerId);
float x2 = (e.GetX(pointerIndex) - scalePointX) / mScaleFactor;
float y2 = (e.GetY(pointerIndex) - scalePointY) / mScaleFactor;
float dx = (x2 - mLastTouchX);
float dy = (y2 - mLastTouchY);
if (!mScaleDetector.IsInProgress)
{
mPosX += dx;
mPosY += dy;
mLastTouchX = x2;
mLastTouchY = y2;
}
this.Invalidate();
break;
case MotionEventActions.Up:
mActivePointerId = INVALID_POINTER_ID;
break;
case MotionEventActions.Cancel:
mActivePointerId = INVALID_POINTER_ID;
break;
case MotionEventActions.PointerUp:
int pointerIndex2 = (int)(e.Action & MotionEventActions.PointerIndexMask) >> (int)MotionEventActions.PointerIndexShift;
int pointerID = e.GetPointerId(pointerIndex2);
if (pointerID == mActivePointerId)
{
int newPointerIndex = pointerIndex2 == 0 ? 1 : 0;
mLastTouchX = (e.GetX(newPointerIndex) - scalePointX) / mScaleFactor;
mLastTouchY = (e.GetY(newPointerIndex) - scalePointY) / mScaleFactor;
mActivePointerId = e.GetPointerId(newPointerIndex);
}
break;
}
return true;
}
private class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener
{
public override bool OnScale(ScaleGestureDetector detector)
{
scalePointX = detector.FocusX;
scalePointY = detector.FocusY;
mScaleFactor *= detector.ScaleFactor;
mScaleFactor = Math.Max(0.5f, Math.Min(mScaleFactor, 7.0f));
return true;
}
}
}