2016-06-27 31 views
2

我有一個縮放,一切都適合一個Canvas更好:如何使MotionEvent的座標與縮放畫布的座標相匹配?

@Override 
public void draw(Canvas c){ 
    super.draw(c); 
    final float scaleFactorX = getWidth()/(WIDTH*1.f); 
    final float scaleFactorY = getHeight()/(HEIGHT*1.f); 

    if(c!=null) { 
     final int savedState = c.save(); 

     c.scale(scaleFactorX, scaleFactorY); 

     (rendering) 

     c.restoreToCount(savedState); 
    } 

} 

它縮放基於這兩個:

public static final int WIDTH = 856; 
public static final int HEIGHT = 1050; 

這會導致問題,處理觸摸事件的MotionEvent的座標是不等於使用Canvas創建的座標。當我嘗試檢查MotionEvent Rect和基於渲染比例的類的Rect之間的衝突時,會導致問題。這會導致類SuperCoin的X座標不等於MotionEvent X座標。 通常,MotionEvent座標,X和Y大於屏幕的最大尺寸(由WIDTHHEIGHT定義)

@Override 
public boolean onTouchEvent(MotionEvent e) { 
    super.onTouchEvent(e); 

    switch (MotionEventCompat.getActionMasked(e)) { 
     case MotionEvent.ACTION_DOWN: 
     case MotionEvent.ACTION_POINTER_DOWN: 
      (...) 
      Rect r = new Rect((int)e.getX(), (int)e.getY(), (int)e.getX() + 3, (int)e.getY() + 3); 
      if(superCoins.size() != 0) { 
       for (SuperCoin sc : superCoins) { 
        if (sc.checkCollision(r)) { 
         progress++; 
         superCoins.remove(sc); 
        } 
       } 
      } 

      break; 

    } 

    return true; 

} 

而且SuperCoin方式更大:

public class SuperCoin { 
    private Bitmap bm; 
    public int x, y, orgY; 
    Clicker cl; 
    private Long startTime; 
    Random r = new Random(); 
    public SuperCoin(Bitmap bm, int x, int y, Clicker c){ 
     this.x = x; 
     this.y = y; 
     this.orgY = y; 
     this.bm = bm; 
     this.cl = c; 
     startTime = System.nanoTime(); 
     bounds = new Rect(x, y, x + bm.getWidth(), y + bm.getHeight()); 

    } 

    private Rect bounds; 

    public boolean checkCollision(Rect second){ 
     if(second.intersect(bounds)){ 
      return true; 
     } 
     return false; 
    } 


    private int velX = 0, velY = 0; 


    public void render(Canvas c){ 

     long elapsed = (System.nanoTime()-startTime)/1000000; 
     if(elapsed>50) { 


      int cx; 
      cx = r.nextInt(2); 
      if(cx == 0){ 
       velX = r.nextInt(4); 
      }else if(cx == 1){ 
       velX = -r.nextInt(4); 
      } 

      velY = r.nextInt(10) + 1; 

      startTime = System.nanoTime(); 
     } 

     if(x < 0) velX = +2; 
     if(x > Clicker.WIDTH) velX = -2; 

     x += velX; 
     y -= velY; 


     c.drawBitmap(bm, x, y, null); 
    } 
} 

如何檢查之間的碰撞當MotionEvent X座標大於屏幕的縮放最大座標時,兩個不同?

老實說,我並不完全確定爲什麼SuperCoin類中定義的Rect與onTouchEvent方法中定義的Rect不同。我猜是因爲X和Y在MotionEvent定義的和由縮放畫布定義的定義之間永遠是不同的。 SuperCoin類中的Rect按照它傳遞的位圖的寬度。它使用位圖的寬度和高度來縮放它。

回答

0

通過StackOverflow和谷歌過去兩天尋找接近解決方案的東西后,我回過頭來:在Android中縮放或拖動後獲取Canvas座標解決了問題。這是真的很難找到,因爲標題是有些誤導

float px = e.getX()/mScaleFactorX; 
float py = e.getY()/mScaleFactorY; 
int ipy = (int) py; 
int ipx = (int) px; 
Rect r = new Rect(ipx, ipy, ipx+2, ipy+2); 

我說這是一個答案(的其它問題),並接受它,所以它,因爲它是解決不再將是一個懸而未決的問題。上面的代碼將座標轉換爲整數,以便它們可用於檢查手指和我正在檢查的對象之間的碰撞。

-1

不要直接縮放畫布。製作矩陣對象,縮放一次。然後將其連接到畫布。然後,您可以爲您的觸摸事件製作一個倒陣。

而只是使反轉矩陣只要更改視圖矩陣:

viewMatrix = new Matrix(); 
viewMatrix.scale(scalefactor,scalefactor); 
invertMatrix = new Matrix(viewMatrix); 
invertMatrix.invert(invertMatrix); 

然後這兩個矩陣應用到相關事件。

@Override 
    public boolean onTouchEvent(MotionEvent event) { 
     event.transform(invertMatrix); 

然後在繪製事件上,連接矩陣。

@Override 
protected void onDraw(Canvas canvas) { 
    canvas.concat(viewMatrix); 

大功告成。一切都爲你照顧。無論你對視圖矩陣做什麼修改都會改變你的視框,你的觸摸事件也會被轉換到同一場景中。

如果您想添加平移或旋轉,甚至傾斜視圖,這一切都照顧。只需將其應用於矩陣,得到倒置矩陣,視圖就會以這種方式看待,並且觸摸事件將按照您的預期進行響應。

+0

這是基於兩個尺度相同的事實。如果X尺度與Y尺度不同,會怎樣? – Zoe

+0

然後它工作得很好。 – Tatarize

+0

viewMatrix.postScale(scale,scale,x,y); --- >> viewMatrix.postScale(scale,1,x,y); ----看到它工作。 https://www.youtube.com/watch?v=GCG3i709g-Y&feature=youtu.be – Tatarize