Android 的觸摸事件詳解及示例代碼
由于觸摸(Touch)而觸發(fā)的事件
Android的事件:onClick, onScroll,onFling等等,都是由許多個(gè)Touch組成的。其中Touch的第一個(gè)狀態(tài)肯定是ACTION_DOWN,表示按下了屏幕。之后,touch將會(huì)有后續(xù)事件,可能是:
ACTION_MOVE //表示為移動(dòng)手勢(shì)
ACTION_UP //表示為離開屏幕
ACTION_CANCEL //表示取消手勢(shì),不會(huì)由用戶產(chǎn)生,而是由程序產(chǎn)生的
一個(gè)Action_DOWN, n個(gè)ACTION_MOVE, 1個(gè)ACTION_UP,就構(gòu)成了Android中眾多的事件。
對(duì)于ViewGroup類的控件,有一個(gè)很重要的方法,就是onInterceptTouchEvent(),用于處理事件并改變事件的傳遞方向,它的返回值是一個(gè)布爾值,決定了Touch事件是否要向它包含的子View繼續(xù)傳遞,這個(gè)方法是從父View向子View傳遞。
而方法onTouchEvent(),用于接收事件并處理,它的返回值也是一個(gè)布爾值,決定了事件及后續(xù)事件是否繼續(xù)向上傳遞,這個(gè)方法是從子View向父View傳遞。
touch事件在onInterceptTouchEvent()和onTouchEvent以及各個(gè)childView間的傳遞機(jī)制完全取決于onInterceptTouchEvent()和onTouchEvent()的返回值。返回值為true表示事件被正確接收和處理了,返回值為false表示事件沒有被處理,將繼續(xù)傳遞下去。
ACTION_DOWN事件會(huì)傳到某個(gè)ViewGroup類的onInterceptTouchEvent,如果返回false,則DOWN事件繼續(xù)向子ViewGroup類的onInterceptTouchEvent傳遞,如果子View不是ViewGroup類的控件,則傳遞給它的onTouchEvent。
如果onInterceptTouchEvent返回了true,則DOWN事件傳遞給它的onTouchEvent,不再繼續(xù)傳遞,并且之后的后續(xù)事件也都傳遞給它的onTouchEvent。
如果某View的onTouchEvent返回了false,則DOWN事件繼續(xù)向其父ViewGroup類的onTouchEvent傳遞;如果返回了true,則后續(xù)事件會(huì)直接傳遞給其onTouchEvent繼續(xù)處理。(后續(xù)事件只會(huì)傳遞給對(duì)于必要事件ACTION_DOWN返回了true的onTouchEvent)
總結(jié)一下就是:onInterceptTouchEvent可以接受到所有的Touch事件,而onTouchEvent則不一定。
對(duì)于android 自定義控件的事件 android提供了一個(gè)GestureDetector的類和GestureDetector.OnGestureListener的接口來判斷用戶在界面上做出怎么樣的動(dòng)作。
Android里有兩個(gè)類
android.view.GestureDetector
android.view.GestureDetector.SimpleOnGestureListener
(另外android.widget.Gallery好像是更牛x的OnGestureListener )
1) 新建一個(gè)類繼承SimpleOnGestureListener,HahaGestureDetectorListener
可以實(shí)現(xiàn)以下event事件。
boolean onDoubleTap(MotionEvent e)
解釋:雙擊的第二下Touch down時(shí)觸發(fā)
boolean onDoubleTapEvent(MotionEvent e)
解釋:雙擊的第二下Touch down和up都會(huì)觸發(fā),可用e.getAction()區(qū)分。
boolean onDown(MotionEvent e)
解釋:Touch down時(shí)觸發(fā)
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY)
解釋:Touch了滑動(dòng)一點(diǎn)距離后,up時(shí)觸發(fā)。
void onLongPress(MotionEvent e)
解釋:Touch了不移動(dòng)一直Touch down時(shí)觸發(fā)
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY)
解釋:Touch了滑動(dòng)時(shí)觸發(fā)。
void onShowPress(MotionEvent e)
解釋:Touch了還沒有滑動(dòng)時(shí)觸發(fā)
?。ㄅconDown,onLongPress比較
onDown只要Touch down一定立刻觸發(fā)。
而Touchdown后過一會(huì)沒有滑動(dòng)先觸發(fā)onShowPress再是onLongPress。
所以Touchdown后一直不滑動(dòng),onDown->onShowPress->onLongPress這個(gè)順序觸發(fā)。
?。?br />
boolean onSingleTapConfirmed(MotionEvent e)
boolean onSingleTapUp(MotionEvent e)
解釋:上面這兩個(gè)函數(shù)都是在touchdown后又沒有滑動(dòng)(onScroll),又沒有長(zhǎng)按(onLongPress),然后Touchup時(shí)觸發(fā)。
點(diǎn)擊一下非常快的(不滑動(dòng))Touchup:
onDown->onSingleTapUp->onSingleTapConfirmed
點(diǎn)擊一下稍微慢點(diǎn)的(不滑動(dòng))Touchup:
onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
publicclassGestureActivityextendsActivityimplementsOnTouchListener, OnGestureListener { GestureDetector detector; publicGestureActivity(){ detector = new GestureDetector(this); } publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView tv = (TextView) findViewById(R.id.TextView001); //設(shè)置tv的監(jiān)聽器 tv.setOnTouchListener(this); tv.setFocusable(true); //必須,view才能夠處理不同于Tap(輕觸)的hold tv.setClickable(true); tv.setLongClickable(true); detector.setIsLongpressEnabled(true); } publicbooleanonTouch(View v,MotionEvent event) { returndetector.onTouchEvent(event); } // 用戶輕觸觸摸屏,由1個(gè)MotionEventACTION_DOWN觸發(fā) publicbooleanonDown(MotionEventarg0) { Log.i("MyGesture","onDown"); Toast.makeText(this, "onDown",Toast.LENGTH_SHORT).show(); returntrue; } publicvoidonShowPress(MotionEvent e) { Log.i("MyGesture","onShowPress"); Toast.makeText(this, "onShowPress",Toast.LENGTH_SHORT).show(); } // 用戶(輕觸觸摸屏后)松開,由一個(gè)1個(gè)MotionEventACTION_UP觸發(fā) publicbooleanonSingleTapUp(MotionEvent e) { Log.i("MyGesture","onSingleTapUp"); Toast.makeText(this, "onSingleTapUp",Toast.LENGTH_SHORT).show(); returntrue; } // 用戶按下觸摸屏、快速移動(dòng)后松開,由1個(gè)MotionEventACTION_DOWN, 多個(gè)ACTION_MOVE, 1個(gè)ACTION_UP觸發(fā) publicbooleanonFling(MotionEvente1, MotionEvent e2, float velocityX, float velocityY) { Log.i("MyGesture","onFling"); // 參數(shù)解釋: // e1:第1個(gè)ACTION_DOWNMotionEvent // e2:最后一個(gè)ACTION_MOVEMotionEvent // velocityX:X軸上的移動(dòng)速度,像素/秒 // velocityY:Y軸上的移動(dòng)速度,像素/秒 // 觸發(fā)條件 : // X軸的坐標(biāo)位移大于FLING_MIN_DISTANCE,且移動(dòng)速度大于FLING_MIN_VELOCITY個(gè)像素/秒 finalintFLING_MIN_DISTANCE = 100,FLING_MIN_VELOCITY = 200; if (e1.getX() - e2.getX() >FLING_MIN_DISTANCE &&Math.abs(velocityX) > FLING_MIN_VELOCITY){ // Flingleft Log.i("MyGesture","Fling left"); Toast.makeText(this, "FlingLeft",Toast.LENGTH_SHORT).show(); } elseif (e2.getX() - e1.getX() >FLING_MIN_DISTANCE &&Math.abs(velocityX) > FLING_MIN_VELOCITY){ // Flingright Log.i("MyGesture","Fling right"); Toast.makeText(this, "FlingRight",Toast.LENGTH_SHORT).show(); } elseif(e2.getY()-e1.getY()>FLING_MIN_DISTANCE && Math.abs(velocityY)>FLING_MIN_VELOCITY) { // Flingdown Log.i("MyGesture","Fling down"); Toast.makeText(this, "Flingdown",Toast.LENGTH_SHORT).show(); } elseif(e1.getY()-e2.getY()>FLING_MIN_DISTANCE && Math.abs(velocityY)>FLING_MIN_VELOCITY) { // Fling up Log.i("MyGesture","Fling up"); Toast.makeText(this, "Flingup",Toast.LENGTH_SHORT).show(); } returnfalse; } // 用戶按下觸摸屏,并拖動(dòng),由1個(gè)MotionEventACTION_DOWN, 多個(gè)ACTION_MOVE觸發(fā) publicbooleanonScroll(MotionEvente1, MotionEvent e2, float distanceX, float distanceY) { Log.i("MyGesture","onScroll"); Toast.makeText(this, "onScroll",Toast.LENGTH_LONG).show(); returntrue; } // 用戶長(zhǎng)按觸摸屏,由多個(gè)MotionEventACTION_DOWN觸發(fā) publicvoidonLongPress(MotionEvent e) { Log.i("MyGesture","onLongPress"); Toast.makeText(this, "onLongPress",Toast.LENGTH_LONG).show(); } }
2)在view的新建一個(gè)GestureDetector的對(duì)象。
構(gòu)造函數(shù)里
gestureDetector = new GestureDetector(newHahaGestureDetectorListener());
然后在View的onTouchEvent里以下這樣用,就可以在剛才1)弄的事件里寫自己的代碼了。
@Override public boolean onTouchEvent(MotionEvent event) { gestureDetector.onTouchEvent(event); } mTouchListener = new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub float x =event.getXPrecision()*event.getX()+event.getX(); float y =event.getYPrecision()*event.getY()+event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: mTouchTimes++; if (mTouchTimes > TOUCH_TIMES) { // 根據(jù)方向計(jì)算角度 if (mCurrentOrientation==DeviceOrientation.Landscape) { mAngle = Math.toDegrees(Math.atan2(y - 480 / 2, x))+90; } else { mAngle = -Math.toDegrees(Math.atan2(y - 480 / 2,320-x))+90; } Log.w("angle", "mangle:"+mAngle); } break; case MotionEvent.ACTION_UP: if (mTouchTimes > TOUCH_TIMES) { } else { } mTouchTimes = 0; break; default: break; } return true; } }; mView.setOnTouchListener(mTouchListener);
通過此文,希望能幫助開發(fā)Android應(yīng)用使用觸摸事件的朋友,謝謝大家對(duì)本站的支持!
相關(guān)文章
Android MVVM架構(gòu)實(shí)現(xiàn)RecyclerView列表詳解流程
MVVM是Model-View-ViewModel的簡(jiǎn)寫。它本質(zhì)上就是MVC 的改進(jìn)版。MVVM 就是將其中的View 的狀態(tài)和行為抽象化,讓我們將視圖 UI 和業(yè)務(wù)邏輯分開2021-10-10android實(shí)現(xiàn)來電靜音示例(監(jiān)聽來電)
這篇文章主要介紹了手機(jī)來電鈴聲響起后,通過此代碼實(shí)現(xiàn)靜音而非掛斷的方法的相關(guān)資料2014-03-03MVVMLight項(xiàng)目的綁定及各種使用場(chǎng)景示例分析
這篇文章主要為大家介紹了MVVMLight項(xiàng)目中的綁定及綁定的各種使用場(chǎng)景示例源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步除夕快樂2022-01-01flutter 自定義websocket路由的實(shí)現(xiàn)
這篇文章主要介紹了flutter 自定義websocket路由的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Android開發(fā) -- setTag的妙用和The key must be an application-specif
本文主要介紹Android開發(fā)setTag的妙用,小編覺得挺實(shí)用的,給大家一個(gè)參考,希望對(duì)大家學(xué)習(xí)有所幫助。2016-06-06Android筆記之:App調(diào)試的幾個(gè)命令的實(shí)踐與分析
本篇文章介紹了,在Android中:App調(diào)試的幾個(gè)命令的實(shí)踐與分析。需要的朋友參考下2013-04-04Android通過記住密碼功能學(xué)習(xí)數(shù)據(jù)存儲(chǔ)類SharedPreferences詳解及實(shí)例
這篇文章主要通過“記住密碼”實(shí)例功能學(xué)習(xí)為大家介紹了Android數(shù)據(jù)存儲(chǔ)類SharedPreferences,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-03-03Flutter實(shí)現(xiàn)心動(dòng)的動(dòng)畫特效
為了追求更好的用戶體驗(yàn),有時(shí)候我們需要一個(gè)類似心跳一樣跳動(dòng)著的控件來吸引用戶的注意力。本文將利用Flutter實(shí)現(xiàn)這一動(dòng)畫特效,需要的可以參考一下2022-04-04Android開發(fā) Activity和Fragment詳解
本文主要介紹Android開發(fā) Activity和Fragment,這里對(duì)Activity和Fragment的知識(shí)做了詳細(xì)講解,并附簡(jiǎn)單代碼示例,有興趣的小伙伴可以參考下2016-08-08