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 //表示為離開(kāi)屏幕
ACTION_CANCEL //表示取消手勢(shì),不會(huì)由用戶(hù)產(chǎn)生,而是由程序產(chǎn)生的
一個(gè)Action_DOWN, n個(gè)ACTION_MOVE, 1個(gè)ACTION_UP,就構(gòu)成了Android中眾多的事件。
對(duì)于ViewGroup類(lèi)的控件,有一個(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表示事件沒(méi)有被處理,將繼續(xù)傳遞下去。
ACTION_DOWN事件會(huì)傳到某個(gè)ViewGroup類(lèi)的onInterceptTouchEvent,如果返回false,則DOWN事件繼續(xù)向子ViewGroup類(lèi)的onInterceptTouchEvent傳遞,如果子View不是ViewGroup類(lèi)的控件,則傳遞給它的onTouchEvent。
如果onInterceptTouchEvent返回了true,則DOWN事件傳遞給它的onTouchEvent,不再繼續(xù)傳遞,并且之后的后續(xù)事件也都傳遞給它的onTouchEvent。
如果某View的onTouchEvent返回了false,則DOWN事件繼續(xù)向其父ViewGroup類(lèi)的onTouchEvent傳遞;如果返回了true,則后續(xù)事件會(huì)直接傳遞給其onTouchEvent繼續(xù)處理。(后續(xù)事件只會(huì)傳遞給對(duì)于必要事件ACTION_DOWN返回了true的onTouchEvent)
總結(jié)一下就是:onInterceptTouchEvent可以接受到所有的Touch事件,而onTouchEvent則不一定。
對(duì)于android 自定義控件的事件 android提供了一個(gè)GestureDetector的類(lèi)和GestureDetector.OnGestureListener的接口來(lái)判斷用戶(hù)在界面上做出怎么樣的動(dòng)作。
Android里有兩個(gè)類(lèi)
android.view.GestureDetector
android.view.GestureDetector.SimpleOnGestureListener
?。硗鈇ndroid.widget.Gallery好像是更牛x的OnGestureListener )
1) 新建一個(gè)類(lèi)繼承SimpleOnGestureListener,HahaGestureDetectorListener
可以實(shí)現(xiàn)以下event事件。
boolean onDoubleTap(MotionEvent e)
解釋?zhuān)弘p擊的第二下Touch down時(shí)觸發(fā)
boolean onDoubleTapEvent(MotionEvent e)
解釋?zhuān)弘p擊的第二下Touch down和up都會(huì)觸發(fā),可用e.getAction()區(qū)分。
boolean onDown(MotionEvent e)
解釋?zhuān)篢ouch down時(shí)觸發(fā)
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY)
解釋?zhuān)篢ouch了滑動(dòng)一點(diǎn)距離后,up時(shí)觸發(fā)。
void onLongPress(MotionEvent e)
解釋?zhuān)篢ouch了不移動(dòng)一直Touch down時(shí)觸發(fā)
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY)
解釋?zhuān)篢ouch了滑動(dòng)時(shí)觸發(fā)。
void onShowPress(MotionEvent e)
解釋?zhuān)篢ouch了還沒(méi)有滑動(dòng)時(shí)觸發(fā)
?。ㄅconDown,onLongPress比較
onDown只要Touch down一定立刻觸發(fā)。
而Touchdown后過(guò)一會(huì)沒(méi)有滑動(dòng)先觸發(fā)onShowPress再是onLongPress。
所以Touchdown后一直不滑動(dòng),onDown->onShowPress->onLongPress這個(gè)順序觸發(fā)。
?。?br />
boolean onSingleTapConfirmed(MotionEvent e)
boolean onSingleTapUp(MotionEvent e)
解釋?zhuān)荷厦孢@兩個(gè)函數(shù)都是在touchdown后又沒(méi)有滑動(dòng)(onScroll),又沒(méi)有長(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)聽(tīng)器 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); } // 用戶(hù)輕觸觸摸屏,由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(); } // 用戶(hù)(輕觸觸摸屏后)松開(kāi),由一個(gè)1個(gè)MotionEventACTION_UP觸發(fā) publicbooleanonSingleTapUp(MotionEvent e) { Log.i("MyGesture","onSingleTapUp"); Toast.makeText(this, "onSingleTapUp",Toast.LENGTH_SHORT).show(); returntrue; } // 用戶(hù)按下觸摸屏、快速移動(dòng)后松開(kāi),由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ù)解釋?zhuān)? // 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; } // 用戶(hù)按下觸摸屏,并拖動(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; } // 用戶(hù)長(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)弄的事件里寫(xiě)自己的代碼了。
@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);
通過(guò)此文,希望能幫助開(kāi)發(fā)Android應(yīng)用使用觸摸事件的朋友,謝謝大家對(duì)本站的支持!
相關(guān)文章
Android MVVM架構(gòu)實(shí)現(xiàn)RecyclerView列表詳解流程
MVVM是Model-View-ViewModel的簡(jiǎn)寫(xiě)。它本質(zhì)上就是MVC 的改進(jìn)版。MVVM 就是將其中的View 的狀態(tài)和行為抽象化,讓我們將視圖 UI 和業(yè)務(wù)邏輯分開(kāi)2021-10-10android實(shí)現(xiàn)來(lái)電靜音示例(監(jiān)聽(tīng)來(lái)電)
這篇文章主要介紹了手機(jī)來(lái)電鈴聲響起后,通過(guò)此代碼實(shí)現(xiàn)靜音而非掛斷的方法的相關(guān)資料2014-03-03MVVMLight項(xiàng)目的綁定及各種使用場(chǎng)景示例分析
這篇文章主要為大家介紹了MVVMLight項(xiàng)目中的綁定及綁定的各種使用場(chǎng)景示例源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步除夕快樂(lè)2022-01-01flutter 自定義websocket路由的實(shí)現(xiàn)
這篇文章主要介紹了flutter 自定義websocket路由的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Android開(kāi)發(fā) -- setTag的妙用和The key must be an application-specif
本文主要介紹Android開(kāi)發(fā)setTag的妙用,小編覺(jué)得挺實(shí)用的,給大家一個(gè)參考,希望對(duì)大家學(xué)習(xí)有所幫助。2016-06-06Android筆記之:App調(diào)試的幾個(gè)命令的實(shí)踐與分析
本篇文章介紹了,在Android中:App調(diào)試的幾個(gè)命令的實(shí)踐與分析。需要的朋友參考下2013-04-04Android通過(guò)記住密碼功能學(xué)習(xí)數(shù)據(jù)存儲(chǔ)類(lèi)SharedPreferences詳解及實(shí)例
這篇文章主要通過(guò)“記住密碼”實(shí)例功能學(xué)習(xí)為大家介紹了Android數(shù)據(jù)存儲(chǔ)類(lèi)SharedPreferences,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-03-03Flutter實(shí)現(xiàn)心動(dòng)的動(dòng)畫(huà)特效
為了追求更好的用戶(hù)體驗(yàn),有時(shí)候我們需要一個(gè)類(lèi)似心跳一樣跳動(dòng)著的控件來(lái)吸引用戶(hù)的注意力。本文將利用Flutter實(shí)現(xiàn)這一動(dòng)畫(huà)特效,需要的可以參考一下2022-04-04Android開(kāi)發(fā) Activity和Fragment詳解
本文主要介紹Android開(kāi)發(fā) Activity和Fragment,這里對(duì)Activity和Fragment的知識(shí)做了詳細(xì)講解,并附簡(jiǎn)單代碼示例,有興趣的小伙伴可以參考下2016-08-08