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;
}
}
}