提示記憶:應用流程:在Activity中對控件執行 view.setOnTouchListener( OnTouchListener i);實現里面的OnTouchListener 接口中的方法,重點再於理解里面的方法的實現步驟,
觸摸,手勢操作已經很好的融入了我們的生活。那么
Android
開發中觸摸事件要如何捕捉?如何處理?如何識別手勢?事件的傳遞機制又是怎么樣的?下面我們將通過一個小例子來進行這方面的學習。
先看效果圖
<ignore_js_op>

如上圖所示,就是一個跟隨手指移動的按鈕。用來演示我們接下來要說的
onTouch
事件和手勢操作。
為了讓大家看懂里面的代碼,我們來先介紹一下基礎知識。
onTouch事件
做什么都好先了解原理以后的工作就會更簡單,關於手勢以及我們熟悉的
onclick
,
onLongClick
事件都是基於對
onTouch
事件的捕捉和處理。那么在使用手勢工具類的前提下我們應該去學習了解基本的
onTouch
事件。
onTouch
常用的以下
4
個事件:
1、ACTION_DOWN:
表示按下了屏幕,第一個執行也是必然執行的方法。
2、ACTION_MOVE:
表示為移動手勢,會不斷的執行直到觸摸停止。
3、ACTION_UP :
表示為離開屏幕,觸摸停止的時候執行。
4、ACTION_CANCEL:
表示取消手勢,不會由用戶產生,而是由程序產生的。
一個
Action_DOWN,
多個
ACTION_MOVE, 1
個
ACTION_UP
,就構成了
Android
中眾多的事件。
onTouch的參數
View
受到
Touch
事件的
view
對象
MotionEvent
包含的事件的詳細信息,例如觸摸點的信息,觸摸事件類型的信息等
MotionEvent
的方法例如
getRowX
所描述的都是觸摸點的信息。
幾個重要方法的說明:
getRowX
:觸摸點相對於屏幕的坐標
getX
: 觸摸點相對於
view
的坐標
getTop
: 按鈕左上角相對於父
view
(
LinerLayout
)的
y
坐標
getLeft
: 按鈕左上角相對於父
view
(
LinerLayout
)的
x
坐標
onTouch的返回值
這個部分涉及到事件傳遞和處理機制,詳細的不在此介紹。
作用:
這里的返回值代表的是,對於這個觸摸事件
touch
是否已經處理完成。
如果我們設置返回值為
true
代表的是處理完成,這樣就不會再傳遞給下一個對象。也就是說后面的控件或者對象就不會接收到觸摸事件了。
反之,后面的對象或控件會在此接收到這個觸摸事件並被調用。
實踐
在學習基礎知識之后,我們來看看如何使用這些來實現一個可以拖動的按鈕吧。
思路
這里的主要思路就是在
ACTION_DOWN
按下的第一時間記錄下初始的狀態,在
ACTION_MOVE
滑動事件中不斷的刷新按鈕的位置。
為了保證有我們正常理解下的點擊事件發生,下面我還加了位置是否移動的判斷。
下面是實現該功能的內部類
class MyOnTouch implements OnTouchListener{ int[] temp = new int[] { 0, 0 }; Boolean ismove = false; int downX = 0; int downY = 0; @Override public boolean onTouch(View v, MotionEvent event) { int eventaction = event.getAction(); int x = (int) event.getRawX(); int y = (int) event.getRawY(); switch (eventaction) { case MotionEvent.ACTION_DOWN: // touch down so check if the temp[0] = (int) event.getX(); temp[1] = y - v.getTop(); downX = (int) event.getRawX(); downY = (int) event.getRawY(); ismove = false; break; case MotionEvent.ACTION_MOVE: // touch drag with the ball v.layout(x - temp[0], y - temp[1], x + v.getWidth() - temp[0], y - temp[1] + v.getHeight()); if (Math.abs(downX - x) > 10 || Math.abs(downY - y) > 10) ismove = true; break; case MotionEvent.ACTION_UP: if (!ismove) Toast.makeText(MainActivity.this, "你點擊了這個按鈕", Toast.LENGTH_LONG).show(); break; } return false; } }
然后在給按鈕初始化的時候設置這個事件
touchButton.setOnTouchListener(new MyOnTouch());
手勢操作
關於手勢操作,這里其實說的是
Android
提供的工具類,通過
GestureDetector
類來識別和處理
onTouch
事件,簡化使用。
一般用到下面的三個類。
android.view.GestureDetector
手勢操作的識別類,通過他來使用下面的識別接口。
android.view.GestureDetector.SimpleOnGestureListener
手勢識別的接口類,使用他可以按需重載自己想要的方法,方法多
android.view.GestureDetector.OnGestureListener;
手勢識別的類,
SimpleOnGestureListener
接口的父類。使用他需要實現他所有的方法。
方法說明:
OnGestureListener有下面的幾個方法:
按下(
onDown
):
在按下時調用。
拋擲(
onFling
):
手指在觸摸屏上迅速移動,並松開的動作。
長按(
onLongPress
):
手指按在持續一段時間,並且沒有松開。
滾動(
onScroll
):
手指在觸摸屏上滑動。
按住(
onShowPress
):
手指按在觸摸屏上,它的時間范圍在按下起效,在長按之前。
抬起(
onSingleTapUp
):
手指離開觸摸屏的那一剎那。
SimpleOnGestureListener比OnGestureListener多出來的方法:
雙擊(
onDoubleTap
)
雙擊的第二下
Touch down
時觸發
雙擊事件(
onDoubleTapEvent
)
雙擊的第二下
Touch down
和
up
都會觸發一次,可用
e.getAction()
區分。
實踐
好了,學習完了基礎知識之后我們來用手勢操作的工具類來實現我們的小按鈕吧。
下面來實現我們的手勢操作內部類。這里我直接實現了
OnGestureListener
接口,為了更好的演示效果。
class MyGesture implements OnTouchListener, OnGestureListener { GestureDetector myGesture = new GestureDetector(MainActivity.this,this); View view = null; int[] temp = new int[] { 0, 0 }; @Override public boolean onTouch(View v, MotionEvent event) { //這一步只是我的強迫症而已,因為onTouch事件是不斷被調用的 if(view == null) view = v; myGesture.onTouchEvent(event); return false; } //在按下時調用 @Override public boolean onDown(MotionEvent e) { temp[0] = (int) e.getX(); temp[1] = ((int) e.getRawY()) - view.getTop(); return false; } //手指在觸摸屏上迅速移動,並松開的動作。 @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; } //長按的時候調用 @Override public void onLongPress(MotionEvent e) { } //按住然后滑動時調用 @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { int x = (int) e2.getRawX(); int y = (int) e2.getRawY(); view.layout(x - temp[0], y - temp[1], x + view.getWidth() - temp[0], y - temp[1] + view.getHeight()); return false; } // 用戶輕觸觸摸屏,尚未松開或拖動,由一個1個MotionEvent ACTION_DOWN觸發 // 注意和onDown()的區別,強調的是沒有松開或者拖動的狀態 @Override public void onShowPress(MotionEvent e) { } // 用戶(輕觸觸摸屏后)松開,由一個1個MotionEvent ACTION_UP觸發 @Override public boolean onSingleTapUp(MotionEvent e) { Toast.makeText(MainActivity.this, "你點擊了按鈕", Toast.LENGTH_LONG).show(); return false; } }
然后在使用的時候給我們的按鈕設置進去就好了
touchButton.setOnTouchListener(new MyGesture());
在內部類的開頭初始化我們的GestureDetector 處理類
GestureDetector myGesture = new GestureDetector(MainActivity.this,this);
[Java] 純文本查看 復制代碼 ? 1 GestureDetector myGesture = new GestureDetector(MainActivity.this,this); 在onTouch方法中調用GestureDetector 的方法 [Java] 純文本查看 復制代碼 ? 1 myGesture.onTouchEvent(event); 關於按鈕功能的說明: 可以拖動的按鈕,這個功能的核心代碼是 [Java] 純文本查看 復制代碼 ? 1 v.layout(x - temp[0], y - temp[1], x + v.getWidth() - temp[0], y - temp[1] + v.getHeight()); 在滑動事件中調用 [Java] 純文本查看 復制代碼 ? 1 view.layout(int l, int t, int r, int b)