2012-03-19 18 views
4

を調整します。私は(2行以下)規模のフォーカスポイントを使用するようにコードを追加するまで、それは素晴らしい作品:アンドロイドは - ズームピンチontouchイベントは、私が作成していアンドロイドアプリの座標私はキャンバスを取得しようとしている

scalePoint.setX((int) detector.getFocusX()); 
scalePoint.setY((int) detector.getFocusY()); 

ここに私のビュークラスのための私のソースコードです:

package us.kniffin.Jigsaw; 

import android.app.AlertDialog; 
import android.content.Context; 
import android.content.DialogInterface; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Rect; 
import android.view.GestureDetector.SimpleOnGestureListener; 
import android.view.MotionEvent; 
import android.view.ScaleGestureDetector; 
import android.view.View; 

public class TestView extends View { 
    private float mLastTouchX; 
    private float mLastTouchY; 
    private float mPosX; 
    private float mPosY; 

    private Rect rect; 

    private float cX, cY; // circle coords 


    // Scaling objects 
    private ScaleGestureDetector mScaleDetector; 
    private float mScaleFactor = 1.f; 
    // The focus point for the scaling 
    private float scalePointX; 
    private float scalePointY; 


    public TestView(Context context) { 
     super(context); 

     mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) {  
     super.onDraw(canvas); 
     Paint p = new Paint(); 
     p.setColor(Color.RED); 

     rect = canvas.getClipBounds(); 

     canvas.save(); 
     canvas.scale(mScaleFactor, mScaleFactor, scalePointX, scalePointY); 
     canvas.translate(mPosX, mPosY); 
     canvas.drawCircle(cX, cY, 10, p); 

     canvas.restore(); 

    } 

    @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()/mScaleFactor;// screen X position 
      final float y = ev.getY()/mScaleFactor;// screen Y position 

      cX = x - (rect.left * mScaleFactor) - mPosX; // canvas X 
      cY = y - (rect.top * mScaleFactor) - mPosY; // canvas Y 

      // Remember where we started 
      mLastTouchX = x; 
      mLastTouchY = y; 
      break; 
     } 
     case MotionEvent.ACTION_MOVE: { 
      final float x = ev.getX()/mScaleFactor; 
      final float y = ev.getY()/mScaleFactor; 
      cX = x - (rect.left * mScaleFactor) - mPosX; // canvas X 
      cY = y - (rect.top * mScaleFactor) - mPosY; // canvas Y 


      // Only move if the ScaleGestureDetector isn't processing a gesture. 
      if (!mScaleDetector.isInProgress()) { 
       final float dx = x - mLastTouchX; // change in X 
       final float dy = y - mLastTouchY; // change in Y 

       mPosX += dx; 
       mPosY += dy; 

       invalidate(); 
      } 

      mLastTouchX = x; 
      mLastTouchY = y; 

      break; 

     } 
     case MotionEvent.ACTION_UP: { 
      mLastTouchX = 0; 
      mLastTouchY = 0; 
      invalidate(); 
     } 
     } 
     return true; 
    } 

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
     @Override 
     public boolean onScale(ScaleGestureDetector detector) { 
      mScaleFactor *= detector.getScaleFactor(); 
      scalePointX = detector.getFocusX(); 
      scalePointY = detector.getFocusY(); 

      // Don't let the object get too small or too large. 
      mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f)); 

      invalidate(); 
      return true; 
     } 
    } 


} 

すべてのアイデアは、私が何をする必要がありますかこれを稼働させるには?

アップデート:私は同じ問題を持っている他に、コードサンプルを置き換えますが、ここでも

更新必需品に簡素化されます。問題がスケーリング後に発生。スケーリングする前に、座標は正しいですが、その後、座標は、クリックした位置の右と下にあります。ズームアウトすればするほど、間違っているようです。

+0

あなたは同じ効果を発揮する小さなプログラムを作ることができれば答えを得るためにlikelierかもしれません。がんばろう! –

+0

良い提案。私はそれをします。 – dkniffin

+0

もう一つの提案:あなたは正確にcordinates(またはエラー)何のように、何が起こるかを説明する必要があり、彼らは100によるか、常に大/小/ランダム/ ..、なぜあなたはスケールと役に立つかもしれませんそれらのものに常にオフしている場合は、取得 – zapl

答えて

8

ハハ!成功!私は一日中ほとんど私を受け取りましたが、私は推測とチェックの束でそれを理解しました。ここで

は私が必要なコードのビットです:

case MotionEvent.ACTION_DOWN: { 
      final float x = (ev.getX() - scalePointX)/mScaleFactor; 
      final float y = (ev.getY() - scalePointY)/mScaleFactor; 
      cX = x - mPosX + scalePointX; // canvas X 
      cY = y - mPosY + scalePointY; // canvas Y 
[snip] 
} 

そしてACTION_MOVE

+0

うわー、あなたの努力は私の友人に感謝しています。 – yajnesh

1

あなたがキャンバスマトリックスを変更している、スケール、回転(など)を変換を使用するたびに。 一般的に、この行列はキャンバス上にある各(x、y)についてあなたに伝えるために使用されます。 キャンバスを作成すると、行列は単位行列になります。 (1) (1) (1) しかし、これらの変更のいずれかを行うと、この行列も変更されます。 右の座標を知りたい場合は、スケーリング/回転の前にcanvas.save()を使用し、スケーリング後にcanvas.restore()を使用してください。

+0

私は保存と復元を使用していますが、それは私の問題を助けるものではありません。私は上手く理解できていない気がします。私はそれらを間違って使っていますか? – dkniffin

0

のためのコードの同様のビット非常に似およびいくつかの試行錯誤の後に何かをしながら、私は最近、この問題に出くわしましたし、私はこの答え(https://stackoverflow.com/a/9945896/1131180)を適応させることになったグーグルがたくさん:

(eはMotionEventであるので、このコードを使用するのに最適な場所はonTouchまたはonLongPressになります)

mClickCoords = new float[2]; 

//e is the motionevent that contains the screen touch we 
//want to translate into a canvas coordinate 
mClickCoords[0] = e.getX(); 
mClickCoords[1] = e.getY(); 

Matrix matrix = new Matrix(); 
matrix.set(getMatrix()); 

//this is where you apply any translations/scaling/rotation etc. 
//Typically you want to apply the same adjustments that you apply 
//in your onDraw(). 

matrix.preTranslate(mVirtualX, mVirtualY); 
matrix.preScale(mScaleFactor, mScaleFactor, mPivotX, mPivotY); 

// invert the matrix, creating the mapping from screen 
//coordinates to canvas coordinates 
matrix.invert(matrix); 

//apply the mapping 
matrix.mapPoints(mClickCoords); 

//mClickCoords[0] is the canvas x coordinate and 
//mClickCoords[1] is the y coordinate. 

は、ここで適用することができますいくつかの明白な最適化がありますが、私はそれがこの方法をより明確だと思います。

関連する問題