requestDisallowInterceptTouchEvent
getParent().requestDisallowInterceptTouchEvent(true);
//请求父级view不要拦截事件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
lv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
//优先级:onTouchListener > onTouchEvent > OnClickListener
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
TouchSlop:
判断是否滑动
//获取最小滑动距离的常量,和设备有关。小于这个值,认定不是滑动。
int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
VolocityTracker:速度追踪
//第一步:初始化追踪当前事件的速度,一般写在MotionEvent.ACTION_DOWN
private void addVelocityTracker(MotionEvent event) {
if (velocityTracker == null) {
velocityTracker = VelocityTracker.obtain();
}
velocityTracker.addMovement(event);
}
//第三步:重置并回收内存,一般写在MotionEvent.ACTION_UP
private void recycleVelocityTracker() {
if (velocityTracker != null) {
velocityTracker.clear();
velocityTracker.recycle();
velocityTracker = null;
}
}
//第二步:获取当前速度,一般写在MotionEvent.ACTION_MOVE用于判断
private int getScrollVelocity() {
velocityTracker.computeCurrentVelocity(1000);//计算速度
int xVelocity = (int) velocityTracker.getXVelocity();//获取水平方向速度:手指划过的像素数
return velocity;
}
Scroller:
用于view的弹性滑动,实现过渡效果,不是瞬间完成,而是一定时间间隔内完成的。Scroller无法使view滑动,需要和view的computeScroll()方法配合使用才能实现这个功能。
- 创建Scroller的实例
- 调用startScroll()方法来初始化滚动数据并刷新界面
- 重写computeScroll()方法,并在其内部完成平滑滚动的逻辑
Scroller mScroller= new Scroller(context);
//缓慢滑动到指定位置
private void smoothScrollTo(int destX , int destY){
int scrollX=getScrollX();
int delta=destX-scrollX;
mScroller.startScroll(scrollX,0,delta,1000);
invalidate();
}
@Override
public void computeScroll() {
//重写computeScroll()方法,并在其内部完成平滑滚动的逻辑
////判断滚动是否还在继续,true继续,false结束
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
invalidate();
}
}
gestureDetector
三种构造方法:
GestureDetector gestureDetector=new GestureDetector(GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector=new GestureDetector(Context context,GestureDetector.SimpleOnGestureListener listener);
GestureDetector这个类对外提供了两个接口和一个外部类
接口:OnGestureListener,OnDoubleTapListener
内部类:SimpleOnGestureListener
这个外部类,其实是两个接口中所有函数的集成,它包含了这两个接口里所有必须要实现的函数而且都已经重写,但所有方法体都是空的;不同点在于:该类是static class,程序员可以在外部继承这个类,重写里面的手势处理方法。
首先是声明一个GestureDetector,然后重写Button的onTouch函数,将触屏事件交给GestureDetector处理。
public class MainActivity extends Activity {
private Button mButton;
private GestureDetector mGestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGestureDetector = new GestureDetector(this, new MyOnGestureListener());
mButton = (Button) findViewById(R.id.btn_textgesture);
mButton.setOnTouchListener(new 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 SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
Log.i(getClass().getName(), "onSingleTapUp-----" + getActionName(e.getAction()));
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;
}
}
}
推荐:
监听滑动用onTouchEvent
监听双击用GestureDetector
更新view界面的方法
Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。
OnTouchListener和onTouchEvent的区别
OnTouchListener和onTouchEvent一样都是view类里面的,都可以监听事件的down、move、up,但一个是接口类,首字母大写,一个是方法,首字母小写,OnTouchListener优先级大于onTouchEvent,OnTouchListener接口要实现onTouch方法,当OnTouchListener实现方法onTouch返回true不会执行onTouchEvent,返回false才会执行onTouchEvent。