View的事件体系总结

View是Android中所有控件的基类,是一种界面层的控件的一种抽象。

View基础知识

View的位置参数:top左上角纵坐标、left左上角横坐标、right右下角横坐标、bottom右下角纵坐标,相对于View的父容器来说,是一种相对坐标。

 x、y是View左上角的坐标,translationX和translationY是View左上角相对于父容器的偏移量。View在平移时,top、left不改变,改变的是x、y、translationX、translationY。

MotionEvent:手指接触屏幕后所产生的一系列事件。通过点击对象可以得到点击事件发生的x和y坐标,getX/getY 相对于当前View 左上角的x和y坐标,getRawX/getRawY相对于手机屏幕左上角的x和y坐标。

TouchSlop:系统所能识别出的被认为是滑动的最小距离。

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

 VelocityTracker:速度追踪,用于追踪手指在滑动过程中的速度。

        VelocityTracker velocityTracker = VelocityTracker.obtain();
        velocityTracker.addMovement(event);
        velocityTracker.computeCurrentVelocity(1000);
        int xVelocity = (int) velocityTracker.getXVelocity();
        int yVelocity = (int) velocityTracker.getYVelocity();

 GestureDetector:手势检测,用于辅助检测用户的单击、滑动、长按、双击等行为。

 

View的滑动

1.View本身提供的srcollTo/scrollBy方法来实现

mScrollX、mScrollY 分别代表视图内容水平方向和竖直方法的滚动距离。scrollTo和scrooBy来实现滑动,只能将View的内容进行移动,并不能将View本身进行移动。

2.使用动画

View动画、属性动画

 

 3.改变布局参数

改变LayoutParams,右移动100px,将这个view的LayoutParams的marginLeft参数增加100px。或者在View的左边放置一个空的View,默认宽度为0,重新设置新View的宽度达到右移的效果。

 

View的事件分发机制

⭐⭐⭐精华总结

public boolean dispatchTouchEvent(MotionEvent ev)

用来进行事件的分发,如果事件能够传递给当前View,此方法一定会被调用,返回结果受当前View的onTouchEvent和下级的dispatchTouchEvent方法的影响,表示是否消耗当前事件。

 

public boolean onInterceptTouchEvent(MotionEvent event)

在上述方法内部调用,用来判断是否拦截某个事件,如果当前View拦截了某个事件,那么在同一事件序列当中,此方法不会被在调用,返回结果表示是否拦截事件。

 

public boolean onTouchEvent(MotionEvent event)

dispatchTouEvent方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次接收到事件。

 

三者的关系:对于一个根ViewGroup来说,点击事件产生后,首先会传递给它,它的dispatchTouch就会被调用,如果这个ViewGroup的onInterceptTouchEvent方法返回true就表示它要拦截当前事件,接着事件会交给这个ViewGroup的onTouchEvent处理;如果这个ViewGroup的onInterceptTouchEvent方法返回false就表示不拦截,事件就会继续传递给它的子元素,子元素的dispatchTouchEvent方法就调用,如此反复直到事件被最终处理。

public boolean dispatchTouchEvent(MotionEvent ev) {
    boolean consume = false;
    if(onInterceptTouchEvent(ev)) {
        consume = onTouchEvent(ev);
    } else {
        consume = child.dispatchTouchEvent(ev);
    }   
    return consume;
}

 

点击事件分发的传递规则:

事件由下而下的传递规则:当点击事件产生后会由Activity来处理,传递给PhoneWindow,再传递给DecorView,最后传递给顶层的ViewGroup。一般事件传递只考虑ViewGroup的onInterceptTouchEvent方法。对于根ViewGroup,点击事件首先传递给它的dispatchTouchEvent()方法,如果该ViewGroup的onInterceptTouchEvent()返回true,则表示它要拦截这个事件,这个事件就会交给它的onTouchEvent()处理;如果onInterceptTouchEvent()方法返回false,则表示它不拦截这个事件,这个事件会交给它子元素的dispatchTouchEvent()处理,如此反复下去,底层View没有子View,会调用view的dispatchTouchEvent()方法,最终调用View的onTouchEvent()方法。

事件由下而上传递:当点击事件传给底层View时,如果onTouchEvent()方法返回true,则事件由底层View消耗并处理;如果返回false则表示该View不做处理,传递给父View的onTouchEvent()处理,如果父View的onTouchEvent()仍旧返回false,则继续传递给父View的父View处理。

 

Scroller

Scroller本身不能实现View的滑动,需要View的computeScroll方法才能完成弹性滑动,它不断地让View重绘,每次重绘距滑动起始时间都会有一个间隔,小幅度滑动形成弹性滑动。

    private void smoothScrollBy(int dx ,int dy) {
        mScroller.startScroll(getScrollX(),0,dx,0,500);
        invalidate();
    }

 

    public void computeScroll() {
        if(mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
            postInvalidate();
        }
    }

 

posted @ 2019-04-25 12:39  kyun  阅读(257)  评论(0编辑  收藏  举报