1、坐标
核心方法
- getTop():view的顶部离父view的顶部的距离
- getleft():view的左边离父view的左边的距离
- getBottom():view的底部离父view的顶部距离
- getRight():view的右边离父view的左边的距离
- getX():view的左边离父view左边的距离+view的偏移量 getY()同理
- getWidth():获取view自身的宽度 getHeight() 同理
- MotionEvent类中的getX()、getY()、getRawX()、getRawY(),如 getX():获取点击事件距离控件左边的距离
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();
}
}
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