Android 区别普通Touch方法和Scroll
今天想实现这个功能,但只是利用现有的onTouchEvent和GestureDetector感觉做起来有些纠结,原来好像也尝试过,最后搞的程序有点乱,不好维护,那么就利用一下Android程序员最大的优势——源码。
首先想到的ListView既支持点击又支持拖动,就去看源码,首先找的突破点就是:
android.view.ViewTreeObserver.OnTouchModeChangeListener
里面只定义了一个方法;
public void onTouchModeChanged(boolean isInTouchMode);
然后就看了一下ViewTreeObserver,发现除了add等并没有相关的内容,然后就找到ListView的父类android.widget.AbsListView,其中实现了该接口。这里面比较复杂就不详细介绍了,结合OnTouchEvent和onTouchModeChanged能看出它的实现机制,但大致看完没有发现很好的解决问题的办法,由于快回去了,又想尽快解决,这时候就想到了手势识别的类android.view.GestureDetector,其实看它的OnTouchEvent要轻松的多,跟前面的实现机制都很像,但相对简单,不过在这不可能找到问题的直接解决办法,但是理解了GestureDetector的事件分发机制和情况,用起来OnGestureListener就会清晰的多。之后就用最基本的实现机制模拟了两个事件的处理,这里说模拟是指的其实并没有真正完全区分,关于这方面觉着较为复杂,还没理清,应该深入看ListView会有具体的实现。好了,直接贴代码吧,上面几个类可以帮助解决这个问题,也可以深入研究,具体的时候并没有用到handler,如果要响应更多的方法的时候这种机制就很有用了,方便扩展。下面直接展示下代码,也比较简单,就不过多解释了,这里理解为滑动20像素才认为是滑动事件来模拟,只是这次看起来比较清晰,就记录一下。
//---------------------------------------------------------------------------
// 触屏与滑动(仅区分滑动和触屏,如果增加双击等时间需要重新考虑逻辑处理)
//---------------------------------------------------------------------------
private GestureDetector gestureDetector; //用手势识别
//表明没有手势事件
private final int TOUCH_MODE_REST = -1;
//表明触摸了屏幕
private final int TOUCH_MODE_DOWN = 0;
//表明发生了scroll,但仍需进一步确认是否是滑动事件
private final int TOUCH_MODE_SCROLLCHECK = 1;
//当前为滑动状态
private final int TOUCH_MODE_SCROLL = 2;
private int touchMode; //当前touch的状态,利用onDown、OnScroll和ActionUP来区分滑动和触屏
private int tempOffsetX = 0; //定义为scroll之前需要先存储偏移
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_UP){
try {
return handleActionUP(event);
} catch (InaccurateScrollActionHandleException e) {
// TODO Auto-generated catch block
Log.e("DigitBusScreen.onTouchEvent", "Use handleActionUP wrong place");
return false;
}
}
return gestureDetector.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent arg0) {
// TODO Auto-generated method stub
touchMode = TOUCH_MODE_DOWN;
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// TODO Auto-generated method stub
switch(touchMode){
case TOUCH_MODE_DOWN:
case TOUCH_MODE_SCROLLCHECK:
if(Math.abs(tempOffsetX+distanceX)<20){
tempOffsetX += distanceX;
touchMode = TOUCH_MODE_SCROLLCHECK;
}else{
touchMode = TOUCH_MODE_SCROLL;
tempOffsetX = 0;
}
break;
case TOUCH_MODE_SCROLL:
if(distanceX!=0 && (offsetX-distanceX<=0)
&& (offsetX-distanceX>=-(offsetX+(actualLengthBetweenStation+Positions.getStationXLength())*numberOfStation))){
for(Sprite sprite:sprites){
if(sprite instanceof ScrollSprite)
((ScrollSprite)sprite).scrollChangeOffset(-distanceX, 0);
}
offsetX += -distanceX;
}
break;
}
return true;
}
/**
* 处理ACTION_UP的MotionEvent
* @param event
* @return
* @throws InaccurateScrollActionHandleException
*/
private boolean handleActionUP(MotionEvent event) throws InaccurateScrollActionHandleException{
if(event.getAction()!=MotionEvent.ACTION_UP)
throw new InaccurateScrollActionHandleException();
switch(touchMode){
case TOUCH_MODE_SCROLLCHECK:
tempOffsetX = 0;
case TOUCH_MODE_DOWN:
super.onTouchEvent(event);
break;
}
touchMode = TOUCH_MODE_REST;
return true;
}
推荐阅读
-
Android 区别普通Touch方法和Scroll
-
Android中invalidate()和postInvalidate() 的区别及使用方法
-
Android中invalidate()和postInvalidate() 的区别及使用方法
-
php抽象方法和普通方法的区别点总结
-
黑马Android76期学习笔记01基础--day07--广播,有、无序广播、特殊广播接受者、样式和主题,this与context的区别、普通对话框,进度条对话框、帧动画
-
php抽象方法和普通方法的区别点总结
-
Android开发触摸touch事件(补间动画和自定义view使用方法)
-
Android中SurfaceView和普通view的区别及使用
-
Android生成界面的两种方法:setContentView和inflate的区别
-
php 抽象方法和普通方法的区别