編輯:關於Android編程
由於觸摸(Touch)而觸發的事件
Android的事件:onClick, onScroll,onFling等等,都是由許多個Touch組成的。其中Touch的第一個狀態肯定是ACTION_DOWN,表示按下了屏幕。之後,touch將會有後續事件,可能是:
ACTION_MOVE //表示為移動手勢
ACTION_UP //表示為離開屏幕
ACTION_CANCEL //表示取消手勢,不會由用戶產生,而是由程序產生的
一個Action_DOWN, n個ACTION_MOVE, 1個ACTION_UP,就構成了Android中眾多的事件。
對於ViewGroup類的控件,有一個很重要的方法,就是onInterceptTouchEvent(),用於處理事件並改變事件的傳遞方向,它的返回值是一個布爾值,決定了Touch事件是否要向它包含的子View繼續傳遞,這個方法是從父View向子View傳遞。
而方法onTouchEvent(),用於接收事件並處理,它的返回值也是一個布爾值,決定了事件及後續事件是否繼續向上傳遞,這個方法是從子View向父View傳遞。
touch事件在onInterceptTouchEvent()和onTouchEvent以及各個childView間的傳遞機制完全取決於onInterceptTouchEvent()和onTouchEvent()的返回值。返回值為true表示事件被正確接收和處理了,返回值為false表示事件沒有被處理,將繼續傳遞下去。
ACTION_DOWN事件會傳到某個ViewGroup類的onInterceptTouchEvent,如果返回false,則DOWN事件繼續向子ViewGroup類的onInterceptTouchEvent傳遞,如果子View不是ViewGroup類的控件,則傳遞給它的onTouchEvent。
如果onInterceptTouchEvent返回了true,則DOWN事件傳遞給它的onTouchEvent,不再繼續傳遞,並且之後的後續事件也都傳遞給它的onTouchEvent。
如果某View的onTouchEvent返回了false,則DOWN事件繼續向其父ViewGroup類的onTouchEvent傳遞;如果返回了true,則後續事件會直接傳遞給其onTouchEvent繼續處理。(後續事件只會傳遞給對於必要事件ACTION_DOWN返回了true的onTouchEvent)
總結一下就是:onInterceptTouchEvent可以接受到所有的Touch事件,而onTouchEvent則不一定。
對於android 自定義控件的事件 android提供了一個GestureDetector的類和GestureDetector.OnGestureListener的接口來判斷用戶在界面上做出怎麼樣的動作。
Android裡有兩個類
android.view.GestureDetector
android.view.GestureDetector.SimpleOnGestureListener
(另外android.widget.Gallery好像是更牛x的OnGestureListener )
1) 新建一個類繼承SimpleOnGestureListener,HahaGestureDetectorListener
可以實現以下event事件。
boolean onDoubleTap(MotionEvent e)
解釋:雙擊的第二下Touch down時觸發
boolean onDoubleTapEvent(MotionEvent e)
解釋:雙擊的第二下Touch down和up都會觸發,可用e.getAction()區分。
boolean onDown(MotionEvent e)
解釋:Touch down時觸發
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY)
解釋:Touch了滑動一點距離後,up時觸發。
void onLongPress(MotionEvent e)
解釋:Touch了不移動一直Touch down時觸發
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY)
解釋:Touch了滑動時觸發。
void onShowPress(MotionEvent e)
解釋:Touch了還沒有滑動時觸發
(與onDown,onLongPress比較
onDown只要Touch down一定立刻觸發。
而Touchdown後過一會沒有滑動先觸發onShowPress再是onLongPress。
所以Touchdown後一直不滑動,onDown->onShowPress->onLongPress這個順序觸發。
)
boolean onSingleTapConfirmed(MotionEvent e)
boolean onSingleTapUp(MotionEvent e)
解釋:上面這兩個函數都是在touchdown後又沒有滑動(onScroll),又沒有長按(onLongPress),然後Touchup時觸發。
點擊一下非常快的(不滑動)Touchup:
onDown->onSingleTapUp->onSingleTapConfirmed
點擊一下稍微慢點的(不滑動)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);
//設置tv的監聽器
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個MotionEventACTION_DOWN觸發
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();
}
// 用戶(輕觸觸摸屏後)松開,由一個1個MotionEventACTION_UP觸發
publicbooleanonSingleTapUp(MotionEvent e) {
Log.i("MyGesture","onSingleTapUp");
Toast.makeText(this, "onSingleTapUp",Toast.LENGTH_SHORT).show();
returntrue;
}
// 用戶按下觸摸屏、快速移動後松開,由1個MotionEventACTION_DOWN, 多個ACTION_MOVE, 1個ACTION_UP觸發
publicbooleanonFling(MotionEvente1, MotionEvent e2, float velocityX, float velocityY) {
Log.i("MyGesture","onFling");
// 參數解釋:
// e1:第1個ACTION_DOWNMotionEvent
// e2:最後一個ACTION_MOVEMotionEvent
// velocityX:X軸上的移動速度,像素/秒
// velocityY:Y軸上的移動速度,像素/秒
// 觸發條件 :
// X軸的坐標位移大於FLING_MIN_DISTANCE,且移動速度大於FLING_MIN_VELOCITY個像素/秒
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;
}
// 用戶按下觸摸屏,並拖動,由1個MotionEventACTION_DOWN, 多個ACTION_MOVE觸發
publicbooleanonScroll(MotionEvente1, MotionEvent e2, float distanceX, float distanceY) {
Log.i("MyGesture","onScroll");
Toast.makeText(this, "onScroll",Toast.LENGTH_LONG).show();
returntrue;
}
// 用戶長按觸摸屏,由多個MotionEventACTION_DOWN觸發
publicvoidonLongPress(MotionEvent e) {
Log.i("MyGesture","onLongPress");
Toast.makeText(this, "onLongPress",Toast.LENGTH_LONG).show();
}
}
2)在view的新建一個GestureDetector的對象。
構造函數裡
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) {
// 根據方向計算角度
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);
通過此文,希望能幫助開發Android應用使用觸摸事件的朋友,謝謝大家對本站的支持!
Android 自定義View時使用TypedArray配置樣式屬性詳細介紹
Android 自定義View時使用TypedArray配置樣式屬性詳細介紹 在自定義v
Android Tab標簽的使用基礎
Android程序中,Tab標簽窗口是一種常用的UI界面元素。它的實現主要是利用了TabHost類。TabHost說明TabHost是一個標簽窗口的容器。一個TabHos
Android中ImageView使用網絡圖片資源的方法
本文實例講述了Android中ImageView使用網絡圖片資源的方法。分享給大家供大家參考。具體如下:很多時候我們不想把東西都放在APK裡面,或者是不能放進去,這時候我
Android手機線刷教程
本教程為通用教程 幾乎適合所有的安卓手機 希望可以幫到酷愛刷機的機油們!注意 不支持win8 支持win7/