view的体系归档篇

101 阅读4分钟

1、坐标

核心方法

  1. getTop():view的顶部离父view的顶部的距离
  2. getleft():view的左边离父view的左边的距离
  3. getBottom():view的底部离父view的顶部距离
  4. getRight():view的右边离父view的左边的距离
  5. getX():view的左边离父view左边的距离+view的偏移量 getY()同理
  6. getWidth():获取view自身的宽度 getHeight() 同理
  7. MotionEvent类中的getX()、getY()、getRawX()、getRawY(),如 getX():获取点击事件距离控件左边的距离

Android View体系(一)视图坐标系:

2、view的滑动

点击事件触发的核心方法是view的onTouchEvent 通过我们之前motionEvent的getx等方法获取移动距离 再通过layout进行设置新位置。通过Scroller类实现也是很多的

当然通过layoutParam、动画、scrollTo()、scrollBy()、scroller类(可以实现平滑)等方式也都可以做到

Android View体系(二)实现View滑动的六种方法

3、属性动画

视图动画的优势是效率高,但是最大缺陷是不改变view真实位置,不能交互、所以现在基本上都是属性动画,但是属性动画的api的确多。后续工作中用到 直接看下面的博客 使用就好了 毕竟这个主要是实战 api实在是记不住! Android View体系(三)属性动画

4、从源码解析Scroller

因为上述我们讲的view的滑动 我们可以通过关注onTouchEvent方法值的改变 然后通过计算 layout方法 或者调用scrollto方法等去改变位置。 但是如果不是通过touch改变而且还需要保证滑动是丝滑 那么就可以使用scroller类。而scroller类的使用,之前我们已经讲过了,这次我们就通过源码去分析为啥能做到。 简单流程就是

先初始化scroller
Scroller scroller = new Scroller(Context context)
scroller.startScroll(scrollX,0,delta,0,2000);
核心是下面这个方法 这个方法执行后会触发draw方法 draw又会触发computeScroll方法
invalidate();

//通过重写该方法 然后mScroller.computeScrollOffset是监听滑动事件是否结束 然后再调用view.scrollTo进行滑动距离计算 然后继续调用invalidate 再次触发draw
@Override
public void computeScroll() {
    super.computeScroll();
    if(mScroller.computeScrollOffset()){
        ((View) getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
         //通过不断的重绘不断的调用computeScroll方法
         invalidate();
    }  
}

ndroid View体系(四)从源码解析Scroller

5、从源码看安卓的事件分发机制(也涉及到事件冲突的处理)非常核心干货了

分为activity、viewgroup、view的事件分发

activity: 我们点击事件 首先是触发activity的dispatchTouchEvent方法,方法体先调用window.dispatchTouchEvent 如果返回true 说明父层处理了,false则后续的ontouchEvent处理。 window.dispatchTouchEvent调用的其实是phoneWindow.dispatchTouchEvent方法 继续调用的是decorView.dispatchTouchEvent方法 也就是viewGroup.dispatchTouchEvent方法。

viewgroup: 先判断onInterceptTouchEvent返回值 如果true 说明拦截 那就自己处理。那就调用super.dispatchTouchEvent(ev);也就是view的dispatchTouchEvent。 false的话 那就查找viewGroup的子类的dispatchTouchEvent是否存在返回为true的。如果没有 继续执行super.dispatchTouchEvent(ev);即View.dispatchTouchEvent() 存在的话 那就将逻辑下沉到view的dispatchTouchEvent

view: 也是先走dispatchTouchEvent方法 第一步是先判断ontouch

 if ( (mViewFlags & ENABLED_MASK) == ENABLED && 
              mOnTouchListener != null &&  
              mOnTouchListener.onTouch(this, event)) {  
            return true;  
        } 

如果这返回true 那么后续的onTouchEvent就不会执行。如果false 那就继续执行 ,我们会在onTouchEvent中 如果aciton是up的情况下 我们会判断onclickListener是否存在 如果存在 则就执行onClick方法。

特别注意一种场景 就是当子view的onTouchEvent返回值是false的时候 后续的事件(move up)都不在消费,这个是为什么呢 ,可参考下面的文章里面提到的最新版本源码分析那篇文章 安卓-事件分发、拦截源码分析,当然 该篇文章也涉及到讲解事件冲突的处理。

从源码解析Activity的构成

Android View体系(六)从源码解析Activity的构成

从源码解析View的measure layout和draw流程

Android View体系(七)从源码解析View的measure流程
Android View体系(八)从源码解析View的layout和draw流程

自定义View viewGroup 组合控件

Android View体系(九)自定义View
Android View体系(十)自定义组合控件
Android View体系(十一)自定义ViewGroup