2012-10-06 43 views
1

我試圖從Android中的MotionEvent s序列中準確讀取ACTION_MOVE delta。避免在Android中合併ACTION_MOVE MotionEvents

我在屏幕上滑動手指的測試表明,在初始ACTION_DOWN之後,幾個MotionEvent不會傳送給收聽者。只有在進行了足夠大的移動後,ACTION_MOVE事件纔會以相對較大的增量傳送。在第一個ACTION_MOVE事件之後,所有的三角洲都再次變得非常小。

或者,也可以觸摸屏幕(0​​)並略微移動,但根本沒有ACTION_MOVE事件發送。

據我所知,對於許多用途來說,具有某種移動靈敏度是有益的。但是,是否有辦法避免ACTION_MOVE事件的合併,以便每個小的初始移動都交付?是否有可以在ACTION_DOWN職位和第一個ACTION_MOVE職位之間的最小距離上設置的閾值?

下面是一些示例代碼:

private float lastX; 
private float lastY; 

public boolean onTouch(View v, MotionEvent ev) { 

    final float y = ev.getX(); 
    final float x = ev.getY(); 

    final int hs = ev.getHistorySize(); 

    final int ac = ev.getAction(); 
    switch(ac) 
    { 
     case MotionEvent.ACTION_DOWN: 
     { 
      this.lastX = x; 
      this.lastY = y; 
      Log.i("TEST", "Down at " + x + "/" + y + " (History size="+hs+")"); 
      return true; 
     } 
     case MotionEvent.ACTION_MOVE: 
     { 
      Log.i("TEST", "Move at " + x + "/" + y + ": Delta="+(lastX-x)+"/"+(lastY-y) + " (History size="+hs+")"); 
      this.lastX = x; 
      this.lastY = y; 
      return true; 
     } 
     case MotionEvent.ACTION_UP: 
     { 
      Log.i("TEST", "Up at " + x + "/" + y + " (History size="+hs+")"); 
      return true; 
     } 
    } 
} 

以及相應的輸出:

Down at 376.0/259.0 (History size=0) 
Move at 392.0/268.0: Delta=-16.0/-9.0 (History size=0) 
Move at 394.0/268.0: Delta=-2.0/0.0 (History size=0) 
Move at 395.0/269.0: Delta=-1.0/-1.0 (History size=0) 
Move at 394.0/268.0: Delta=1.0/1.0 (History size=0) 
Move at 396.0/269.0: Delta=-2.0/-1.0 (History size=0) 
Move at 399.0/271.0: Delta=-3.0/-2.0 (History size=1) 
Move at 401.0/272.0: Delta=-2.0/-1.0 (History size=0) 
Move at 403.0/273.0: Delta=-2.0/-1.0 (History size=0) 
Move at 404.0/273.0: Delta=-1.0/0.0 (History size=0) 
Move at 405.0/274.0: Delta=-1.0/-1.0 (History size=0) 
Move at 406.0/275.0: Delta=-1.0/-1.0 (History size=0) 
Up at 406.0/275.0 (History size=0) 

換句話說,我想避免在第二行中的大的增量(-16/-9 ),但接收1或2的順序增量...

我對三星Galaxy S2和筆記做了測試。

任何幫助或建議,高度讚賞!

+1

它是在運動或死區時間之後的ACTION_DOWN,在此期間,ACTION_MOVEs被禁用死區?也許你可能想嘗試找出哪一個。 – NickT

+0

您可以通過使用event.getHistoricalX/Y()方法 – Sameer

+0

這絕對是在運動的死區獲得更多的積分。當(1)觸摸('ACTION_DOWN')並保持手指穩定並且在一秒開始移動之後或(2)在等待的情況下在屏幕上滑動時,可以觀察到相同的行爲。第一個'ACTION_MOVE'事件具有總是最大的三角洲 - 好像有需要**最小增量**的'ACTION_DOWN'後報告了'ACTION_MOVE'之前。 – msto

回答

1

我在一些應用程序中使用MotionEvent,並且necer面臨此問題。

如果您使用SDK版本> 4,則MotionEvent支持多點觸控。我正在測試這個在我的應用程序,並使用修改過的監聽器來獲取觸摸事件。代碼波紋管:

private static PointF touchScreenStartPtArr[] = new PointF[10]; 
private static PointF touchScreenStopPtArr[] = new PointF[10]; 
private static PointF touchScreenCurrPtArr[] = new PointF[10]; 

OnTouchListener onTouchListenerMulti = new OnTouchListener() { 

    @Override 
    public boolean onTouch(View v, MotionEvent event) { 

     int action = event.getAction() & MotionEvent.ACTION_MASK; 
     int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
     int fingerId = event.getPointerId(pointerIndex); 

     switch (action) { 
     case MotionEvent.ACTION_DOWN: 
     case MotionEvent.ACTION_POINTER_DOWN: 
      touchScreenStartPtArr[fingerId].x = event.getX(pointerIndex); 
      touchScreenStartPtArr[fingerId].y = event.getY(pointerIndex); 
      break; 
     case MotionEvent.ACTION_UP: 
     case MotionEvent.ACTION_POINTER_UP: 
     case MotionEvent.ACTION_CANCEL: 
      touchScreenStopPtArr[fingerId].x = event.getX(pointerIndex); 
      touchScreenStopPtArr[fingerId].y = event.getX(pointerIndex); 
      break; 
     case MotionEvent.ACTION_MOVE: 
      int pointerCount = event.getPointerCount(); 
      for (int i = 0; i < pointerCount; i++) { 
       touchScreenCurrPtArr[fingerId].x = event.getX(i); 
       touchScreenCurrPtArr[fingerId].y = event.getY(i); 
      } 
      break; 
     } 
     return true; 
    } 
}; 

- 編輯 -

運行代碼在設備華爲X5的結果:

10-06 17:35:48.509:I/TEST(2051):下來387.29388/247.27272(歷史大小= 0)

10-06 17:35:48.529:I/TEST(2051):移動在387.29388/247.27272:德爾塔= 0.0/0.0(歷史大小= 0)

10-06 17:35:48.619:I/TEST(2051):移動到387.2 9388/247.27272:Delta = 0.0/0.0(歷史大小= 0)

10-06 17:35:49.300:I/TEST(2051):移動到387.29388/245.39589:Delta = 0.0/1.876831(歷史記錄大小= 0)

10-06 17:35:49.650:I/TEST(2051):移動在387.29388/244.92668:德爾塔= 0.0/0.46920776(歷史大小= 0)

10-06 17時35: 49.840:I/TEST(2051):移動387.29388/244.45747:Delta = 0.0/0.46920776(歷史記錄大小= 0)

10-06 17:35:50。021:I/TEST(2051):移動387.29388/243.98827:Delta = 0.0/0.46920776(歷史記錄大小= 0)

10-06 17:35:50.221:I/TEST(2051):移動到387.29388/243.51906:Delta = 0.0/0.46920776(歷史記錄大小= 0)

10-06 17:35:50.241:I/TEST(2051):在389.01614/243.51906處移動:Delta = -1.7222595/0.0(歷史記錄大小= 0 )

10-06 17:35:50.531:I/TEST(2051):移動在389.8773/243.51906:德爾塔= -0.861145/0.0(歷史大小= 0)

10-06 17點35: 50.561:I/TEST(2051):移動在389.8773/243.04985:德爾塔= 0.0/0.46920776(歷史大小= 0)

10-06 17:35:50.781:I/TEST(2051):移動在390.73843/243.04985:德爾塔= -0.861145/0.0(歷史大小= 0)

10-06 17:35:50.861 :I/TEST(2051):在390.73843/242.58064移動:Delta = 0.0/0.46920776(歷史記錄大小= 0)

10-06 17:35:51.052:I/TEST(2051):移動391.59958/242.58064 (歷史記錄大小= 0):Delta = -0.861145/0.0(歷史大小= 0)

10-06 17:35:51.172:I/TEST(2051):移動391.59958/242.11143:Delta = 0.0/0.46920776

10-06 17:35:5 1.282:I/TEST(2051):移動392.46072/242.11143:Delta = -0.861145/0.0(歷史大小= 0)

10-06 17:35:51.512:I/TEST(2051):移動392.46072 /241.64223:德爾塔= 0.0/0.46920776(歷史大小= 0)

10-06 17:35:51.562:I/TEST(2051):移動在393.32187/241.64223:德爾塔= -0.861145/0.0(歷史尺寸= 0)

10-06 17:35:51.852:I/TEST(2051):移動在394.183/241.64223:德爾塔= -0.861145/0.0(歷史大小= 0)

10-06 17時35分:51.892:I/TEST(2051):移動在394.183/241.17302:德爾塔= 0.0/0.46920776(歷史大小= 0)

10-06 17:35:52.163:I/TEST(2051):移動在395.04413/241.17302:德爾塔= -0.8611145/0.0(歷史大小= 0)

10-06 17:35:52.173 :I/TEST(2051):在395.04413/242.11143移動:Delta = 0.0/-0.9384155(歷史記錄大小= 0)

10-06 17:35:52.193:I/TEST 242.58064:德爾塔= 0.0/-0.46920776(歷史大小= 0)

10-06 17:35:52.213:I/TEST(2051):高達在395.04413/242.58064(歷史大小= 0)

它看起來你可能有另一個l istener從這一個竊取事件。

我建議你檢查你的代碼(你需要一個加到底「返回false」)在清洗工程,只是爲了確認。

祝你好運。

+0

謝謝,路易斯。我瞭解多點觸控的含義。不過,我在這裏考慮一個簡單的「單觸式」場景,我只有一個手指,似乎如果第一觸摸後,對第一招事件被觸發之前所需的移動距離的最小閾值。我試圖避免這種行爲,即立即報告任何獨立於閾值的移動。 – msto

+0

@msto你是對的,它不應該使用單一的觸摸有任何區別。我已經在模擬器和華爲x5設備上試過了你的代碼。它沒有顯示你正在報告的問題。我正在編輯發佈日誌的答案。 – Luis

+0

路易斯,這確實很有趣!感謝您進行這項測試。在哪個View元素上註冊了事件偵聽器?我使用了一個橫跨整個視圖端口的普通和空白視圖。也許我需要稍微重命名這個問題,並使其具體到三星手機... – msto

3

我不想打破它給你,但是這完全是三星的故障,只會在銀河S2發生。基本上,他們沒有真正的理由在輸入驅動程序中添加了軟件觸摸閾值。

我曾經試圖說服他們去掉門檻,但他們似乎並沒有明白問題,並告訴我說是故意!儘管如此,他們已經將其固定在Galaxy S3中。

幸運的是沒有硬件限制,所以你可以圍繞它得到,如果你有一個根深蒂固的電話,或者安裝一個定製ROM。

+0

鏈接已損壞。 – rraallvv

+0

對不起,我把它從我的頻道中刪除,因爲...人們還在使用Galaxy S2s嗎?! – Timmmm