Android 屏幕點擊手勢判斷

近期在做一個項目,其中涉及到屏幕點擊事件的手勢判斷,比如是單擊還是雙擊,是左滑還是上滑等。


要獲取到屏幕的點擊事件並不難,只需要重載Acivity的onTouchevent(MotionEvent ev)方法,或者dispatchTouchEvent(MotionEvent ev)方法即可,其中傳入的形參MotionEvent ev,ev即爲點擊事件,我們可以獲取到ev,然後得到點擊事件ev的信息,比如點擊的x座標可以通過ev.getX()得到等。


那麼如何識別是什麼手勢呢?我們可以想到,單擊與雙擊可以通過比較兩次的時間差來判斷,這個時間差閾值是由自己設定的。

而長按可以通過TouchEvent事件的Down動作的時間,和Up動作的時間差來判斷,當然了,這個時間差閾值也是自己設定的。

此兩種比較簡單,不再列代碼。


那麼如何判斷是否是滑動,並判斷是什麼滑動呢?

我們知道,TouchEvent有3中類型,一種是Down,就是按下的動作,一種是Move,就是滑動的動作,還有一種就是Up,於是,我們可以通過判斷按下(Down)和擡起(Up)的位移來判斷是什麼類型的滑動,代碼如下,

<span style="white-space:pre">	</span>public boolean dispatchTouchEvent(MotionEvent ev) {
<span style="white-space:pre">		</span>// TODO Auto-generated method stub
<span style="white-space:pre">		</span>int iAction = ev.getAction();


<span style="white-space:pre">		</span>switch (iAction) {
<span style="white-space:pre">		</span>case MotionEvent.ACTION_DOWN:
<span style="white-space:pre">			</span>int down_x = (int) ev.getX();
<span style="white-space:pre">			</span>int down_y = (int) ev.getY();
<span style="white-space:pre">			</span>
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">		</span>case MotionEvent.ACTION_MOVE:
<span style="white-space:pre">			</span>int move_x = (int) ev.getX();
<span style="white-space:pre">			</span>int move_y = (int) ev.getY();
<span style="white-space:pre">			</span>if (touch_mode == 0) {
<span style="white-space:pre">				</span>touch_mode = 1;
<span style="white-space:pre">				</span>first_move_p_x = move_x;
<span style="white-space:pre">				</span>first_move_p_y = move_y;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">		</span>case MotionEvent.ACTION_UP:
<span style="white-space:pre">			</span>int up_x = (int) ev.getX();
<span style="white-space:pre">			</span>int up_y = (int) ev.getY();
<span style="white-space:pre">			</span>
<span style="white-space:pre">			</span>int x_dis = up_x - first_move_p_x;
<span style="white-space:pre">			</span>int y_dis = up_y - first_move_p_y;
<span style="white-space:pre">			</span>if (Math.abs(x_dis) > Math.abs(y_dis)) {
<span style="white-space:pre">				</span>if ((x_dis) > 100) {
<span style="white-space:pre">					</span>System.out.println("右滑動");
<span style="white-space:pre">				</span>} else if ((x_dis) < -100) {
<span style="white-space:pre">					</span>System.out.println("左滑動");
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>} else {


<span style="white-space:pre">				</span>if ((y_dis) > 100) {
<span style="white-space:pre">					</span>System.out.println("下滑動");
<span style="white-space:pre">				</span>} else if ((y_dis) < -100) {
<span style="white-space:pre">					</span>System.out.println("上滑動");
<span style="white-space:pre">				</span>}
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>touch_mode = 0;
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">		</span>default:
<span style="white-space:pre">			</span>break;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span>return super.dispatchTouchEvent(ev);
<span style="white-space:pre">	</span>}
其中,
touch_mode和<span style="font-family: Arial, Helvetica, sans-serif;">first_move_p_x,</span><span style="font-family: Arial, Helvetica, sans-serif;">first_move_p_y爲全局變量,</span>

</pre>touch_mode的作用是,第一次滑動時改變其值,標記爲滑動,並記下第一次滑動的位置<pre name="code" class="html">first_move_p_x和<span style="font-family: Arial, Helvetica, sans-serif;">first_move_p_y</span>

然後在Up動作中,判斷x方向和y方向的位移來判斷滑動即可,當然,也得設置一個閾值,來判斷是否是滑動,本代碼中設置的是100個像素值。



以上就是自己實現手勢識別的代碼。

其實,Android本身已經提供了判斷手勢的API,包括在GestureDetector中,代碼如下,

<pre name="code" class="java">GestureDetector <span style="font-family: Arial, Helvetica, sans-serif;">getstureDetector = new GestureDetector(context, new mGestureListener());</span>
<span style="font-family: Arial, Helvetica, sans-serif;">其中,</span><span style="font-family: Arial, Helvetica, sans-serif;">mGestureListener重載了</span><span style="font-family: Arial, Helvetica, sans-serif;">SimpleOnGestureListener方法,</span>
<span style="font-family: Arial, Helvetica, sans-serif;">class mGestureListener extends GestureDetector.SimpleOnGestureListener
</span>

<span style="font-family: Arial, Helvetica, sans-serif;">SimpleOnGestureListener內有幾個接口,</span>
<span style="font-family: Arial, Helvetica, sans-serif;"></span><p>public boolean onSingleTapUp(MotionEvent ev) {</p><p> <wbr>  <wbr> Log.d("onSingleTapUp",ev.toString());</wbr></wbr></p><p> <wbr>  <wbr> return true;</wbr></wbr></p><p> <wbr> }</wbr></p><p> <wbr> @Override</wbr></p><p> <wbr> public void onShowPress(MotionEvent ev) {</wbr></p><p> <wbr>  <wbr> Log.d("onShowPress",ev.toString());</wbr></wbr></p><p> <wbr> }</wbr></p><p> <wbr> @Override</wbr></p><p> <wbr> public void onLongPress(MotionEvent ev) {</wbr></p><p> <wbr>  <wbr> Log.d("onLongPress",ev.toString());</wbr></wbr></p><p> <wbr> }</wbr></p><p>…</p>
其具體接口的含義,可以看其文檔,很容易看懂。

但是,關於該API是怎麼實現的,是不是和自己實現的機制一樣,我不確定,等有時間研究了源碼再來分享。

第一次發博客,謝謝大家支持。






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章