2017-01-27 7 views
1

ビューから、ビットマップを描画し、 スケールにしたいと思って、それを限界までドラッグしたいと思います。 私の仕事は完全な写真を見るためにギャラリーで使用されるImageViewを作成しています。 私はスケールとドラッグを実現しましたが、限界を認識し始めたとき、canvas.scale(mScale、mSaleale、mid.x、mid.y)の画像位置は変更されましたが、mX、mYの値は変更されませんでした。 このため、私は中点を使ってスケールを作成し、mXとmYを手動で変更しました。 この値を手動で変更する際に問題があります。キャンバスを中間点でスケーリングした後のAndroidのフィックス座標

私のクラス:

public class ZoomImageView2 extends View { 

private File imageFile; 
private Bitmap bitmap; 

private static final int NONE = 0; 
private static final int DRAG = 1; 
private static final int ZOOM = 2; 
private int mode = NONE; 


private PointF start = new PointF(); 
private PointF mid = new PointF(); 
private float oldDist = 1f; 
private float d = 0f; 
private float newRot = 0f; 
private float[] lastEvent = null; 

private int mX = 0, mY = 0; 
private float mScale = 1f; 

private Rect clipBounds_canvas; 

private Handler mainHadler; 

public ZoomImageView2(Context context) { 
    super(context); 
    mainHadler = new Handler(Looper.getMainLooper()); 
} 

public ZoomImageView2(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    mainHadler = new Handler(Looper.getMainLooper()); 
} 

public ZoomImageView2(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    mainHadler = new Handler(Looper.getMainLooper()); 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    //super.onDraw(canvas); 
    if (bitmap != null) { 
     canvas.save(); 
     clipBounds_canvas = canvas.getClipBounds(); 
     Log.w("SCALING_ZOOMIMAGE2", mX + " " + mY + " " + mScale); 
     canvas.scale(mScale, mScale); 
     canvas.drawBitmap(bitmap, mX, mY, new Paint()); 
     canvas.restore(); 
    } 
} 

public void setImageFile(final File imageFile) { 
    this.imageFile = imageFile; 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      bitmap = BitmapHelper.getINSTANCE().getSampledBitmapFromFile(imageFile.getAbsolutePath(), getResources().getDisplayMetrics().widthPixels, getResources().getDisplayMetrics().widthPixels); 
      new Handler(Looper.getMainLooper()).post(new Runnable() { 
       @Override 
       public void run() { 
        if (bitmap.getWidth() >= bitmap.getHeight()) { 
         mStableScale = (float) getResources().getDisplayMetrics().widthPixels/(float) bitmap.getWidth(); 
        } else { 
         mStableScale = (float) getResources().getDisplayMetrics().heightPixels/(float) bitmap.getHeight(); 
        } 
        mScale = mStableScale; 
        invalidate(); 
       } 
      }); 
     } 
    }).start(); 
} 

int mOldX, mOldY; 
float mOldScale = 1f; 
float mStableScale; 
float maxScale = 5f; 


@Override 
public boolean onTouchEvent(MotionEvent event) { 
    switch (event.getAction() & MotionEvent.ACTION_MASK) { 
     case MotionEvent.ACTION_DOWN: 
      start.set(event.getX(), event.getY()); 
      mode = DRAG; 
      lastEvent = null; 
      mOldX = mX; 
      mOldY = mY; 
      mOldScale = mScale; 
      break; 

     case MotionEvent.ACTION_POINTER_DOWN: 

      oldDist = spacing(event); 
      if (oldDist > 10f) { 
       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: 
      if (mScale < mStableScale) { 
       animateScaleTo(false); 
      } 
      if (mScale > maxScale) { 
       animateScaleTo(true); 
      } 

     case MotionEvent.ACTION_POINTER_UP: 

      mode = NONE; 
      lastEvent = null; 
      break; 

     case MotionEvent.ACTION_MOVE: 

      if (mode == DRAG) { 
       mX = (int) ((event.getX() - start.x)/mScale + mOldX); 
       mY = (int) ((event.getY() - start.y)/mScale + mOldY); 

      } else if (mode == ZOOM) { 
       float newDist = spacing(event); 

       if (newDist > 10f) { 
        mScale = (newDist/oldDist) * mOldScale; 
        mX = (int)-(getResources().getDisplayMetrics().widthPixels/2 * (mScale -1) - mOldX*mScale); 
        mY = (int)-(getResources().getDisplayMetrics().heightPixels/2 * (mScale -1) - mOldY*mScale); 
        //TODO! 
       } 

       if (lastEvent != null && event.getPointerCount() == 3) { 

        //newRot = rotation(event); 
        //float r = newRot - d; 
        //float[] values = new float[9]; 
        //matrix.getValues(values); 
        //float tx = values[2]; 
        //float ty = values[5]; 
        //float sx = values[0]; 
        //float xc = (view.getWidth()/2) * sx; 
        //float yc = (view.getHeight()/2) * sx; 
        //matrix.postRotate(r, tx + xc, ty + yc); 

       } 
      } 
      break; 
    } 
    invalidate(); 
    return true; 
} 

private void animateScaleTo(final boolean forMax) { 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       int waiting = 1; 
       if (forMax) { 
        waiting = (int) (100/((mScale - maxScale)/0.05)); 
       } else { 
        waiting = (int) (100/((mStableScale - mScale)/0.05)); 
       } 
       if (waiting == 0) waiting = 1; 
       while (forMax ? mScale >= maxScale : mScale <= mStableScale) { 
        if (forMax) { 
         mScale -= 0.05; 
        } else { 
         mScale += 0.05; 
        } 
        mainHadler.post(new Runnable() { 
         @Override 
         public void run() { 
          invalidate(); 
         } 
        }); 
        Thread.sleep(waiting); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }).start(); 
} 


private void animateTranslateX(final boolean forEnd) { 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       int waiting; 
       if (forEnd) { 
        waiting = (int) (300f/(mX - (float) bitmap.getWidth() * mScale)); 
       } else { 
        waiting = (int) (300f/(float) (mX)); 
       } 
       if (waiting == 0) waiting = 1; 
       while (forEnd ? mX > ((float) bitmap.getWidth() * mScale) : mX > 0) { 
        mX -= 5; 
        mainHadler.post(new Runnable() { 
         @Override 
         public void run() { 
          invalidate(); 
         } 
        }); 
        Thread.sleep(waiting); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }).start(); 
} 

private void animateTranslateY(final boolean forEnd) { 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       int waiting; 
       if (forEnd) { 
        waiting = (int) (300/(mY - (float) bitmap.getHeight() * mScale)); 
       } else { 
        waiting = (int) (300/(float) (mY)); 
       } 
       if (waiting == 0) waiting = 1; 
       while (forEnd ? mY > ((float) bitmap.getHeight() * mScale) : mY > 0) { 
        mY -= 5; 
        mainHadler.post(new Runnable() { 
         @Override 
         public void run() { 
          invalidate(); 
         } 
        }); 
        Thread.sleep(waiting); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }).start(); 
} 


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

private void midPoint(PointF point, MotionEvent event) { 
    point.set(getResources().getDisplayMetrics().widthPixels/2, getResources().getDisplayMetrics().heightPixels/2); 
} 

}

私は、所定の位置に問題があります。

if (newDist > 10f) { 
    mScale = (newDist/oldDist) * mOldScale; 
    mX = (int)-(getResources().getDisplayMetrics().widthPixels/2 * (mScale -1) - mOldX*mScale); 
    mY = (int)-(getResources().getDisplayMetrics().heightPixels/2 * (mScale -1) - mOldY*mScale); 
     //TODO! 
    } 

をここで私は値を設定する必要があります。今は間違っている。

私はこの問題を解決するのに多くの時間を費やします。ありがとうございました!コメントで述べたように、次のように は悪い英語

+0

「間違っている」 - 間違った値が設定されるか、何らかのエラーが表示されますか?あなたが間違っていると判断したことは何を見ていますか? –

+0

はい、間違った値が設定され、ビットマップの位置が正しく変更されません。 – androidAnonDev

+0

元の画像のサムネイル、またはより小さなバージョンを作成していることを正しく理解していますか?そうでない場合は、変換が何を期待しているのか、そして実際に何をしているのかを最大限に説明してください。 –

答えて

1

のため申し訳ありませんが、解決策の一部は次のとおりです。次のように変更します。

mX = (int)-(getResources().getDisplayMetrics().widthPixels/2 * (mScale -1) - mOldX*mScale); 
mY = (int)-(getResources().getDisplayMetrics().heightPixels/2 * (mScale -1) - mOldY*mScale); 

へ:

mX = (int)-(getResources().getDisplayMetrics().widthPixels/2 - mOldX*mScale); 
mY = (int)-(getResources().getDisplayMetrics().heightPixels/2 - mOldY*mScale); 

不必要な追加の乗算ステップを削除するにはこれは、画像を大きすぎるサイズにスケーリングする効果を有する。

関連する問題