Android事件分发机制

来源:互联网 发布:无法优化游戏的问题 编辑:程序博客网 时间:2024/06/05 08:27

一、View位置参数
1.top、bottom、left、right:分别表示四个顶点的原始坐标,通过getTop()、getBottom()、getLeft()、getRight()方法获取,这些坐标都是相对于父控件的相对坐标,如果要获取相对于屏幕的绝对坐标可以通过View.getLoactionOnScreen(int[])获得
2.x、y是View左上角相对于父容器的坐标,translationX、translationY是View左上角相对于父容器的偏移量,View也为它们提供了get/set方法
x = left + translationX
y = top + translationY
二、MotionEvent
点击事件发生的x、y:
event.getX()、event.getY():获取相对于当前View左上角的坐标
event.getRawX()、event.getRawY():获取相对于屏幕左上角的坐标
三、ScrollTo/ScrollBy滑动
getScrollX()、getScrollY()分别获取View左边缘和View内容左边缘在水平方向的距离和View上边缘和View内容上边缘在竖直方向的距离,即View左边缘或上边缘的内容的原始坐标,从左向右和从上向下滑动为负值,从右向左和从下向上滑动为正值。
四、
1.TouchSlop:系统所能识别的被认为是滑动的最小距离

ViewConfiguration.get(getContext()).getScaledTouchSlop();

2.VelocityTracker:速度追踪
在onTouchEvent方法中追踪当前点击事件的速度:

        VelocityTracker velocityTracker = VelocityTracker.obtain();        velocityTracker.addMovement(event);        velocityTracker.computeCurrentVelocity(1000);//计算速度        int xVelocity = (int) velocityTracker.getXVelocity();        int yVelocity = (int) velocityTracker.getYVelocity();        velocityTracker.clear();//重置回收内存        velocityTracker.recycle();

3.GestureDetector:手势检测
创建一个GestureDetector对象并实现OnGestureListener接口
在待监听View的onTouchEvent方法中

GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.OnGestureListener(){            @Override            public boolean onDown(MotionEvent e) {                return false;            }            @Override            public void onShowPress(MotionEvent e) {            }            @Override            public boolean onSingleTapUp(MotionEvent e) {                return false;            }            @Override            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {                return false;            }            @Override            public void onLongPress(MotionEvent e) {            }            @Override            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {                return false;            }        });        //解决长按屏幕后无法拖动的现象        gestureDetector.setIsLongpressEnabled(false);        return gestureDetector.onTouchEvent(event);

五、View的滑动
1.使用ScrollTo/ScrollBy
2.使用动画,主要是操作View的translationX和translationY属性
3.改变布局参数getLayoutParams()和setLayoutParams()
六、弹性滑动
1.使用Scoller
invalidate()方法会导致View重绘,在View的draw方法中又会调用computeScroll方法,computeScroll方法在View中是一个空实现,需要自己实现,完成控件的滑动

Scroller scroller = new Scroller(this);        scroller.startScroll(fromX,fromY,deltaX,deltaY,duration);        invalidate();
    @Override    public void computeScroll(){        if(scroller.computeScrollOffset()){            scrollTo(scroller.getCurrX(),scroller.getCurrY());            postInvalidate();        }    }

2.使用值动画

ValueAnimator valueAnimator = ValueAnimator.ofInt(0,100).setDuration(1000);        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                int value = (int) animation.getAnimatedValue();                view.scrollBy(value);            }        });

3.使用延时策略
使用Handler或View的postDelayed方法发送一个延时消息,在消息中进行View的滑动,接连不断地发送这种这种延时消息;
或者使用线程的sleep方法,在while循环中不断地滑动View和sleep;
六、View事件分发机制
事件传递给某View,调用该View的dispatchTouchEvent方法,在该方法内部调用onInterceptTouchEvent方法,返回true,表示拦截,调用onTouchEvent方法,返回true,表示消耗该事件,返回false表示不处理该事件,交给父View的onTouchEvent方法处理;返回false,表示不拦截,将事件继续向下传递给子View,调用子View的dispatchTouchEvent方法。
通过requestDisallowInterceptTouchEvent()方法可以在子元素中干预父元素的事件分发过程,ACTION_DOWN事件除外。
七、滑动冲突
1.外部拦截法
重写父元素的onInterceptTouchEvent()方法,父容器需要此事件则拦截,不需要则不拦截,ACTION_DOWN必须返回false,ACTION_MOVE根据需求来决定是否拦截,ACTION_UP事件也要返回false,否则处理事件的子元素无法接收到ACTION_UP事件。
2.内部拦截法
重写子元素的dispatchTouchEvent()方法,调用parent.requestDisallowInterceptTouchEvent();
如果子元素需要此事件就直接消耗掉,否则就交由父容器处理

0 0
原创粉丝点击