2013-07-31 99 views
2

如何檢查onTouchEvent如果觸摸this isometric one等不規則形狀?Android onTouch不規則形狀

希望你能幫助我。

+1

您是否已將自己的形狀繪製到屏幕上?如果是的話你是怎麼做到的? – FoamyGuy

+1

作爲surfaceView上的位圖。 – Stupe

+0

@FoamyGuy繪製一個形狀並對它進行命中測試是兩件非常不同的事情。 –

回答

1

檢查是否從MotionEvent座標是你的外形內:

@Override 
public boolean onTouchEvent(MotionEvent event) 
{ 
    final float x = event.getX(); 
    final float y = event.getY(); 
    if (isInside(x, y)) 
    { 
     // do something 
    } 
    return true; 
} 

boolean isInside(float x, float y) 
{ 
    // TODO: return true, if (x,y) is inside your shape, otherwise return false 
} 
+0

但我該怎麼做呢? – Stupe

+0

您必須瞭解點擊是如何在形狀中發生的。對於複雜的形狀,存在激光投影。看看你最喜歡的搜索引擎;) – mithrop

+0

點正在被採樣,這意味着如果用戶快速滑動,你將無法判斷他曾經觸摸過這個形狀。 –

1

檢查是否MotionEvent座標是你的外形內,然後做一個點在多邊形擊中測試。

如果您的等角形狀是具有相同長度的段,並具有所有90度的角度(在評論Geobits作爲校正)菱形,快速測試可以使用Manhatten Distance完成。看看鏈接,圖片更清楚爲什麼這個工程。

int rectSize = 10; 
Rectangle diamondBoundingRect = new Rectangle(0,0,rectSize,rectSize); 
Point point = new Point(9,9); 
int dx = Math.abs(point.x - diamondBoundingRect.center.x); 
int dy = Math.abs(point.y - diamondBoundingRect.center.y); 
if(dx+dy < rectSize){ 
    //point is inside diamond 
}else{ 
    //point is not inside diamond 
} 

這個測試是不靈活的,但它可能是所有你需要的。

如果你需要更好的東西,this blog post解釋了點在多邊形命中測試的算法。

這個想法是從你的MotionEvent點將一條線(稱爲Ray)投射到你的多邊形,並計算該線與該多邊形中的線段之間的交點數。如果計數是偶數,則該點在形狀之外。如果它是奇數的話,那麼這個點就在這個形狀中。

Wikipedia has a nice picture和更多的細節,以幫助您瞭解這種做法的邏輯。在獲得該

精礦這個下一部分前工作,因爲它可以根據您的需求證明是不必要的。

onTouchEvent發送給您的點進行採樣。該設備只是以某個預定的速率給你點數和方向。用戶移動手指的速度越快,採樣率無法跟上的細節越少。

所以,如果你想了解更多的細節,你就必須interpolate。這是一種先進的方式,你需要猜測用戶在哪裏用一些花式的數學方法來刷他的手指。在過去,餘弦插值對我來說效果很好,因爲它在速度和結果之間取得了很好的平衡。

編輯:

下面是一些代碼,我用親手爲點在多邊形命中測試。

public boolean isPointInsidePolygon(double x, double y){ 
    //pointAry holds the polygon's vertices. 
    int polySides = this.pointAry.Length; 
    //need at lest 3 vertices to create a polygon. 
    if (polySides < 3) 
    { 
     return false; 
    } 
    int j = polySides - 1; 
    boolean oddNodes = false; 
    for (int i = 0; i < polySides; i++) 
    { 
     Point pi = this.pointAry[i]; 
     Point pj = this.pointAry[j]; 
     if (pi.y < y && pj.y >= y || pj.y < y && pi.y >= y) 
     { 
      if (pi.x + (y - pi.y)/(pj.y - pi.y) * (pj.x - pi.x) < x) 
      { 
       oddNodes = !oddNodes; 
      } 
     } 
     j = i; 
    } 
    return oddNodes; 
} 
+0

你的代碼中「size」是什麼意思? – Stupe

+0

只是矩形的寬度或高度。我編輯了答案。具有所有等長邊的菱形將具有所有等長邊的邊界矩形。大小是任何一個邊界矩形邊的長度。那個例子中的'rectSize'是10. –

+0

好吧,現在我看到我的Shape沒有相同長度的段。我的矩形是46 * 24px。你有清楚的想法如何處理這樣的大小觸摸? – Stupe

0

這是由你來編寫一些代碼,檢測給定點(x,y)是否在你的不規則形狀。

public boolean isInIrregularShape(int x, int y); 

您必須以某種方式定義形狀。您可能希望在Google上搜索某些庫,以便定義一個形狀並檢查給定點是否位於該形狀內。您的x和y點將是event.getX()event.getY()

0

如果您將圖形繪製爲SurfaceView上的位圖,則只需測試所觸及的像素的透明度即可。位圖的像素,即不是SurfaceView的。

例如,在100,150(surfaceview COORDS左/頂)繪製的位圖:

float x = getX() - 100; 
float y = getY() - 150; 
int alpha = Color.alpha(myBitmap.getPixel(x, y)); 
if(alpha == 0) 
    // not hit! 
else 
    // hit! 

注:這並不需要縮放生效,所以你必須要知道的比例因子並且如果你正在繪製它們,則相應地進行相乘。

+0

這也不考慮歪斜或旋轉。 –

+0

的確,這只是一個基礎實現。你還應該首先檢查邊界框。可以在「算法」選項卡中找到更好的答案。 – Geobits

+0

我認爲這會奏效。我會嘗試它並給出評論 – Stupe