View的基本知識
View的位置參數(shù):有四個屬性,top,left,right,bottom。top是左上角的縱坐標(biāo),left是左上角的橫坐標(biāo),bottom是右下角的縱坐標(biāo),right是右下角的橫坐標(biāo)。由此可得:
width = right - left
heightj = bottom - top
這四個屬性的獲取方式:
Left = getLeft();
Right = getRight();
Top = getTop();
Bottom = getBottom();
在Android3.0后,View增加了額外的參數(shù):x,y,translationX和translationY,其中x,y是View左上角的左邊,translationX和translationY是View左上角相對于父容器的偏移量。translationX,translationY的默認(rèn)值為0.
需要注意的是,View在平移過程中,top,left表示的是原始左上角的位置信息,其值并不會改變,此時(shí)改變的是x,y,translationX和translationY這四個參數(shù)。所以:
x = left + translationX
y = top + translationY
MotionEvent
可以通過MotionEvent對象得到點(diǎn)擊事件發(fā)送的x和y坐標(biāo)。為此,系統(tǒng)提供了兩組方法:getX/getY和getRawX/getRawY。getX/getY返回的是相當(dāng)于當(dāng)前View左上角的x和y坐標(biāo),而getRawX和getRawY獲得是相當(dāng)于手機(jī)屏幕左上角的x和y坐標(biāo)。
TouchSlop
TouchSlop是系統(tǒng)所能識別的被認(rèn)為是滑動的最小距離??梢酝ㄟ^ViewConfiguration.get(getContext ()).getScaledTouchSlop()方法來獲取這個常量。
VelocityTracker 速度追蹤
速度追蹤,用于追蹤手指在滑動過程中的速度,包括水平速度和豎直方向速度。他的用法很簡單就,首先,在View的onTouchEvent方法中追蹤當(dāng)前點(diǎn)擊事件的速度:
VelocityTracker velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);
接著,通過如下方式來獲得當(dāng)前的速度:
velocityTracker.computeCurrentVelocity(1000); //先計(jì)算移動速度,1000代表在1000ms中,移動的像素
Int xVelocity = (int) velocityTracker.getXVelocity() ; //獲取剛剛計(jì)算出的1000ms中x軸方向移動的像素
int yVelocity = (int) velocityTracker.getYVelocity(); //獲得剛剛計(jì)算出的1000ms中y軸方向移動的像素
最后當(dāng)不需要使用它的時(shí)候,需要調(diào)用clear方法來重置并回收內(nèi)存
velocityTracker.clear();
velocityTracker.recycle();
GestureDetector
- 第一步:Activity或者View在面對觸摸事件時(shí),可以重寫他們的默寫方法來自定義他們對面觸摸事件的反應(yīng)。對于Activity而言,我們可以直接重寫
onTouchEvent()方法
public class MainActivity extends Activity {
...
// This example shows an Activity, but you would use the same approach if
// you were subclassing a View.
@Override
public boolean onTouchEvent(MotionEvent event){
//對event的處理
return true;
}
對于View而言,我們可以通過View.onTouchListener接口,重寫他的onTouch方法來自定義觸摸事件的處理方式
View myView = findViewById(R.id.my_view);
myView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// ... Respond to touch events
return true;
}
});
- 第二步,在重寫
onTouch方法或者onTouchEvent方法時(shí),我們可以通過GestureDetector類來幫助我們檢測用戶的單擊,滑動,長按,雙擊等行為。在定義GestureDetector中,重寫其中各個方法中,加入我們需要進(jìn)行的操作。
下面的是Activity的例子
public class MainActivity extends Activity implements
GestureDetector.OnGestureListener, //實(shí)現(xiàn)了OnGestureListener接口
GestureDetector.OnDoubleTapListener{ //實(shí)現(xiàn)了雙擊判斷接口
private static final String DEBUG_TAG = "Gestures";
private GestureDetectorCompat mDetector;
// Called when the activity is first created.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Instantiate the gesture detector with the
// application context and an implementation of
// GestureDetector.OnGestureListener
mDetector = new GestureDetectorCompat(this,this);
// Set the gesture detector as the double tap
// listener.
mDetector.setOnDoubleTapListener(this);
}
@Override
public boolean onTouchEvent(MotionEvent event){
this.mDetector.onTouchEvent(event);
// Be sure to call the superclass implementation
return super.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent event) {
Log.d(DEBUG_TAG,"onDown: " + event.toString()); //加入我們需要的操作
return true;
}
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString()); //加入我們需要的操作
return true;
}
@Override
public void onLongPress(MotionEvent event) {
Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); //加入我們需要的操作
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
Log.d(DEBUG_TAG, "onScroll: " + e1.toString()+e2.toString()); //加入我們需要的操作
return true;
}
@Override
public void onShowPress(MotionEvent event) {
Log.d(DEBUG_TAG, "onShowPress: " + event.toString()); //加入我們需要的操作
}
@Override
public boolean onSingleTapUp(MotionEvent event) {
Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString()); //加入我們需要的操作
return true;
}
@Override
public boolean onDoubleTap(MotionEvent event) {
Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString()); //加入我們需要的操作
return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent event) {
Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString()); //加入我們需要的操作
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent event) {
Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString()); //加入我們需要的操作
return true;
}
}
在View中,使用方法如下:在此之前,要定義并初始化mDetector。
View myView = findViewById(R.id.my_view);
myView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
// ... Respond to touch events
this.mDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
});
- 如果你只想實(shí)現(xiàn)一部分GestureDetector.OnGestureLisner接口中的方法,你可以繼承GestureDetector.SimpleOnGestureListener類。這個類實(shí)現(xiàn)了GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, 和 GestureDetector.OnContextClickListener 接口中的所有的方法,但是在實(shí)現(xiàn)了沒有做任何事情,僅僅是
return false;。
public class MainActivity extends Activity {
private GestureDetectorCompat mDetector;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDetector = new GestureDetectorCompat(this, new MyGestureListener());
}
@Override
public boolean onTouchEvent(MotionEvent event){
this.mDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
private static final String DEBUG_TAG = "Gestures";
@Override
public boolean onDown(MotionEvent event) {
Log.d(DEBUG_TAG,"onDown: " + event.toString());
return true;
}
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString());
return true;
}
}
}
不管你是實(shí)現(xiàn)GestureDector.OnGestureListener接口還是繼承GestureDector.SimpleOnGestureListener類,最好都實(shí)現(xiàn)其中的onDown( )方法,即在里面renturn true;。 因?yàn)樗械氖謩荻际?code>onDown()方法開始的,如果你返回了false(正如GestureDector.SimpleOnGestureListener類中默認(rèn)實(shí)現(xiàn)法的), 系統(tǒng)就會認(rèn)為你打算忽略后面所有的手勢,其后面所有的手勢判斷方法都不會執(zhí)行。