- GestureDetector為手勢(shì)識(shí)別類,用來(lái)監(jiān)聽(tīng)回調(diào)用戶對(duì)視圖的操作。
這次我們就分別模擬一些用戶的手勢(shì)事件,來(lái)看看這個(gè)類是怎么回調(diào)的吧
廢話不多說(shuō),直接看代碼。
public class MainActivity extends AppCompatActivity {
private Button mButton;
private GestureDetector mGestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.button);
mGestureDetector = new GestureDetector(this, new MyOnGestureListener());
mButton = (Button) findViewById(R.id.btn_textgesture);
mButton.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.i(getClass().getName(), "onTouch-----" +
getActionName(event.getAction()));
mGestureDetector.onTouchEvent(event);
// 一定要返回true,不然獲取不到完整的事件
return true;
}
});
}
private String getActionName(int action) {
String name = "";
switch (action) {
case MotionEvent.ACTION_DOWN: {
name = "ACTION_DOWN";
break;
}
case MotionEvent.ACTION_MOVE: {
name = "ACTION_MOVE";
break;
}
case MotionEvent.ACTION_UP: {
name = "ACTION_UP";
break;
}
default:
break;
}
return name;
}
class MyOnGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
Log.i(getClass().getName(), "onSingleTapUp-----" +
getActionName(e.getAct ion()));
return false;
}
@Override
public void onLongPress(MotionEvent e) {
Log.i(getClass().getName(), "onLongPress-----" +
getActionName(e.getAction()));
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {
Log.i(getClass().getName(),"onScroll-----" +
getActionName(e2.getAction()) + ",(" + e1.getX() + "," +
e1.getY() + ") ,("+ e2.getX() + "," + e2.getY() + ")");
return false;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.i(getClass().getName(),"onFling-----" +
getActionName(e2.getAction()) + ",(" + e1.getX() + "," + e1.getY()
+ ") ,("+ e2.getX() + "," + e2.getY() + ")");
return false;
}
@Override
public void onShowPress(MotionEvent e) {
Log.i(getClass().getName(), "onShowPress-----" +
getActionName(e.getAction()));
}
@Override
public boolean onDown(MotionEvent e) {
Log.i(getClass().getName(), "onDown-----" +
getActionName(e.getAction()));
return false;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.i(getClass().getName(), "onDoubleTap-----" +
getActionName(e.getAction()));
return false;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
Log.i(getClass().getName(), "onDoubleTapEvent-----" +
getActionName(e.getAction()));
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Log.i(getClass().getName(), "onSingleTapConfirmed-----" + getActionName(e.getAction()));
return false;
}
}
}
視圖的樣子就是一個(gè)空布局里面有一個(gè)button,準(zhǔn)備工作都做好了。
- 我們來(lái)模擬一下單次點(diǎn)擊事件:
這里由于筆者點(diǎn)擊時(shí)抖動(dòng)了一下,所以多調(diào)用了一次<code>onTouch</code>這并不影響我們觀察,根據(jù)Log的順序分析,首先調(diào)用了<code>onTouch</code>Motion是Down,之后馬上調(diào)用<code>onDown</code>,Motion同上,這時(shí)我們應(yīng)該把抬起來(lái)了,所以調(diào)用了<code>onTouch</code>而Motion是Up,最后調(diào)用<code>onSingleTapUp</code>是一次單擊事件,而最后那個(gè)<code>onSingleTapComfirmed</code>方法是用來(lái)判斷這就是一次點(diǎn)擊,一旦調(diào)用這個(gè)方法,后面就不會(huì)出現(xiàn)兩次點(diǎn)擊(雙擊)這樣的事件
,這里筆者有個(gè)問(wèn)題:為什么調(diào)用<code>onSingleTapComfirmed</code>的Motion是Down而不是Up?
如果哪位大神指導(dǎo)這個(gè)問(wèn)題,麻煩在評(píng)論區(qū)指點(diǎn)下,謝啦。
-
之后我們模擬一下雙擊的事件:
雙擊Log
這里依舊出現(xiàn)了Move的Motion...還是不影響觀察,繼第一次點(diǎn)擊之后觀察,<code>onTouch</code>依舊調(diào)用這里就不再說(shuō)了,注意下<code>onDoubleTap</code>他在我們按下去的時(shí)候就已經(jīng)調(diào)用了,之后的方法<code>onDoubleTapEvent</code>就可以用來(lái)監(jiān)聽(tīng)從雙擊第二次Down到第二次Up的所有事件。而且,如果調(diào)用了<code>onDoubleTap</code>,那之后就不能再調(diào)用<code>onSingleTapUp</code>和<code>onSingleTapComfirmed</code>了。
接下來(lái)是長(zhǎng)按效果的模擬:
前面的都是一樣的,從<code>onShowPress</code>開(kāi)始,這個(gè)是一個(gè)按下不滑動(dòng)時(shí)的調(diào)用,如果按的時(shí)間再長(zhǎng)一點(diǎn)就會(huì)調(diào)用<code>onLongPress</code>這就是長(zhǎng)按的實(shí)現(xiàn)。值得一提的是,如果長(zhǎng)按執(zhí)行了,直到用戶Up,其他的事件都不會(huì)觸發(fā),如圖就是筆者長(zhǎng)按后移動(dòng)后的Log。
- 再來(lái)是移動(dòng)的模擬:
這里根據(jù)打印的Log可以發(fā)現(xiàn),調(diào)用了<code>onScroll</code>,這個(gè)方法獲取的坐標(biāo)指的不是滑動(dòng)的距離,而是距離上一次滑動(dòng)的坐標(biāo)。這里說(shuō)的一次滑動(dòng)指的是一整個(gè)事件。最后的<code>onFling</code>這個(gè)字面意思是“拋”,就是滑動(dòng)后沒(méi)有停下就離開(kāi)屏幕,如果不想調(diào)用這個(gè)方法,在滑動(dòng)之后要停一下,親測(cè)有效。
- 最后一點(diǎn)值得注意的是,這些方法除了<code>onLongPress</code>沒(méi)有返回值,其他的方法都有返回值通過(guò)<code>onTouchEvent</code>返回至<code>onTouch</code>。
理解這個(gè)類的事件回調(diào)順序后,相信以后對(duì)用戶的交互事件處理有點(diǎn)幫助。