2011-09-25 56 views
1

我想知道如何爲MotionEvent獲取準確的get(x)和get(y)值?正在發生的事情是,當我觸摸屏幕上的特定區域時,我會告訴一個動作發生。 問題是,一旦我觸摸屏幕並取下手指,它仍然認爲我的手指位於相同的位置(因爲這是我觸摸的最後一個位置)。因此,當我有多個Down事件(用於多點觸控)時,它會拋出所有內容。有沒有辦法重置X和Y值,所以當我放棄屏幕,他們回到0或空(或其他)?MotionEvent問題

這是我剛剛上傳,以便更好地解釋它的視頻,原因它是一種混亂

http://www.youtube.com/watch?v=OHGj2z5SwQs

這裏是我使用

int x = (int) e.getX(); 
    int y = (int) e.getY(); 
    int x2 = (int) e.getX(1); 
    int y2 = (int) e.getY(1); 


    boolean a1 = y > 0 && y < 200....etc   

    boolean a5 = etc... 

    switch (e.getActionMasked()) { 
    case MotionEvent.ACTION_DOWN: 
     x = 0; 
     y = 0;   
     x2 = 0; 
     y2 = 0; 
        ////I'm setting the x and y values to 0 as suggested 

     text.setText("x:" + String.valueOf(x) + "y:" + String.valueOf(y)); 
        //// This is so I can see the values on the screen 
     if (a1 && a5){ 
      viewA1.setBackgroundColor(Color.GREEN); 
      viewA5.setBackgroundColor(Color.GREEN); 
     } 
     if (a1) { 

      viewA1.setBackgroundColor(Color.GREEN); 
     } 



     else if (a5) { 
      viewA5.setBackgroundColor(Color.GREEN); 

     }   



     break; 

    case MotionEvent.ACTION_POINTER_1_DOWN: 
     // /A Strummer 
     x = 0; 
     y = 0; 

     x2 = 0; 
     y2 = 0; 

     text1.setText("x:" + String.valueOf(x2) + "y:" + String.valueOf(y2)); 
     if (a1 && a5){ 

      viewA1.setBackgroundColor(Color.GREEN); 
      viewA5.setBackgroundColor(Color.GREEN); 

     } 
     if (a1) { 

      viewA1.setBackgroundColor(Color.GREEN); 
     } 



     else if (a5) { 

      viewA1.setBackgroundColor(Color.GREEN); 

     }  
    /////I have pretty much the same method for ACTION_UP & ACTION_POINTER_UP; I set x & y to 0. 

請讓確切的代碼我知道你是否可以想到任何事情。我嘗試了你們解釋過的方法,看起來會有所幫助,但事實並非如此。

回答

1

您應該使用'motionEvent.getPoinerCount()'來檢查觸點的數量。

+0

@ Peter Knego我剛纔那樣做,PointerCount是準確的。任何其他想法? – Tanner

5

我沒有提示,但有一個工作解決方案和多點觸控啓動器的一些提示。我從來沒有這樣做過,所以看到你的問題後,我很渴望現在多點觸控的工作原理。實際上,要把它做好是非常困難的。這是一個很好的例子(有四個角的視圖,當其中一個指針觸摸它時,它被着色 - 與一個多達五個指針/手指一起工作)。所以我會根據下面進一步發佈的工作解決方案來解釋它。

基本上它的工作原理是這樣的:getPointerCount()爲您提供了當前觸摸指針的數量。 getX(i)getY(i)正在給你相應的座標。但這部分是棘手的:指針0,1,2觸摸,你擡起1(二指),現在你有0,1。這是getPointerId(1)將返回2的點,因爲這仍然是你的指針2,它觸摸但它現在位於第1位,而是第2位。您有一次機會對這一變化作出反應,那就是當ACTION_POINTER_UP被觸發時。在此動作上並且在ACTION_POINTER_DOWNgetActionIndex()將返回從指針事件列表添加或移除的指針的動作指針位置。否則它總是返回0,這是沒有人告訴你的。

結論是你實際上不能跟蹤哪個指針正在移動(這就是爲什麼getActionIndex()在移動時返回0)。這看起來很合邏輯,因爲每個手指觸發5個單獨事件會很愚蠢。但是,從多點觸控開始,這是一個非常小的事實;-)

下面是示例。 coordsXcoordsY將跟蹤指針座標,如果位置2包含有效座標,則表示這是您的第三根手指,無論您是否擡起其他手指,它仍然會觸摸屏幕。這可能與這種情況無關,但這是一個在其他多點觸控實現中仍然有用的事實。

public class MultitouchView extends LinearLayout { 

    // we have a maximum of 5 pointer 
    // we will set Integer.MIN_VALUE if the pointer is not present 
    private int [] coordsX = new int [5]; 
    private int [] coordsY = new int [5]; 

    // add 4 views with a certain gravity so they are placed in corners 
    public MultitouchView(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     // initialize as not present 
     Arrays.fill(coordsX, Integer.MIN_VALUE); 
     Arrays.fill(coordsY, Integer.MIN_VALUE); 


     /* the layout is inflated from a XML file and is basically this one: 
     * all subviews are matching/filling parent and have a weight of 1 
     * <LinearLayout vertical> 
     * <LinearLayout horizontal> 
     *  <View /><View /> 
     * </LinearLayout> 
     * <LinearLayout horizontal> 
     *  <View /><View /> 
     * </LinearLayout> 
     * </LinearLayout> 
     */ 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent e) { 
     if (e.getAction() == MotionEvent.ACTION_CANCEL) { 
      // every touch is going to be canceled, clear everything 
      Arrays.fill(coordsX, Integer.MIN_VALUE); 
      Arrays.fill(coordsY, Integer.MIN_VALUE); 
     } else { 
      // track all touches 
      for (int i = 0; i < e.getPointerCount(); i++) { 
       int id = e.getPointerId(i); 

       if (e.getActionIndex() == i 
         && (e.getActionMasked() == MotionEvent.ACTION_POINTER_UP 
         || e.getActionMasked() == MotionEvent.ACTION_UP)) { 
        // pointer with this id is about to leave, clear it 
        coordsX[id] = coordsY[id] = Integer.MIN_VALUE; 
       } else { 
        // update all other pointer positions 
        coordsX[id] = (int) e.getX(i); 
        coordsY[id] = (int) e.getY(i); 
       } 
      } 
     } 

     int hw = getWidth()/2; 
     int hh = getHeight()/2; 

     // first no corner is touched 
     boolean topLeft = false, topRight = false, bottomRight = false, bottomLeft = false; 

     // check if any of the given pointer is touching a certain corner 
     for (int i = 0; i < coordsX.length; i++) { 
      // pointer is not active (anymore) 
      if (coordsX[i] == Integer.MIN_VALUE || coordsY[i] == Integer.MIN_VALUE) { 
       continue; 
      } 

      topLeft = topLeft || coordsX[i] < hw && coordsY[i] < hh; 
      topRight = topRight || coordsX[i] > hw && coordsY[i] < hh; 
      bottomRight = bottomRight || coordsX[i] > hw && coordsY[i] > hh; 
      bottomLeft = bottomLeft || coordsX[i] < hw && coordsY[i] > hh; 
     } 

     // set the result we have now to the views represnting the corners 
     ((ViewGroup) getChildAt(0)).getChildAt(0).setBackgroundColor(topLeft ? 0xffffff00 : 0x0); 
     ((ViewGroup) getChildAt(0)).getChildAt(1).setBackgroundColor(topRight ? 0xffff0000 : 0x0); 
     ((ViewGroup) getChildAt(1)).getChildAt(0).setBackgroundColor(bottomLeft ? 0xff00ff00 : 0x0); 
     ((ViewGroup) getChildAt(1)).getChildAt(1).setBackgroundColor(bottomRight ? 0xff0000ff : 0x0); 

     return true; 
    } 
} 
+0

我的回答至少幫助你解決了你的問題嗎? – Knickedi

+0

@ Knickedi我希望我能說出來,但無論如何,這隻會讓事情變得複雜。我不明白爲什麼我試圖實現的代碼將會像您所建議的那樣嚴重,儘管我很可能是錯誤的,因爲我嘗試使用的方法顯然不起作用。 – Tanner

+0

雖然有一個問題,我必須擴展一個View並使用OnTouchEvent,還是我可以擴展一個Activity並在OnTouch上使用?我一直在使用後者,因爲前者似乎對我來說更加複雜。但我不知道,我只學了大約6周的時間學習Java/Android,它似乎一直很順利,直到我擊中它,現在就好像我撞上了一堵磚牆。我想我需要回到基礎知識...... D-: – Tanner