View常用的方法(自定义的时候要重写)
onLayout()
用于对子控件进行布局,相当于绝对布局
onMeasure方法
onMeasure会调用两次
view会先调用该方法对视图的大小进行测量
他的参数
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//两个参数都包含两个信息,测量模式和测量值
int size = MeasureSpec.getSize(widthMeasureSpec);
int mode = MeasureSpec.getMode(widthMeasureSpec);
}
用于测量控件的大小,接受两个参数
widthMeasureSpec
heightMeasureSpec
- 测量模式有三种
- ECACTLY
- AT_OST
- UNSPECIFIED
自己设置view 的大小
setMeasuredDimension(mWidth,mHeigth);
生成带有模式的测量参数
MeasureSpec.makeMeasureSpec(mWidth,MeasureSpec.AT_MOST);
onDraw()
在构造函数中创建画笔
mArcPaint = new Paint();
mArcPaint.setAntiAlias(true);
mArcPaint.setStyle(Paint.Style.STROKE);
mArcPaint.setStrokeWidth(10);
mArcPaint.setColor(Color.GREEN);
在view使用矩阵进行图形的变换
使用matrix绘制矩阵
三个前缀,四个方法
pre post set
Translate Rotate Scale Skew
View提供的获取坐标方法
- getTop():获取到的是View自身的顶边到父布局顶边的距离。
- getLeft():获取到的是View自身的左边到其父布局左边的距离
- getRight():获取的是View自身的右边到其父布局左边的距离
- getBottom():获取的是View自身的底边到其父布局顶边的距离
MotionEvent提供的方法
- getX():获取点击事件距离控件左边的距离,即视图坐标
- getY():获取点击事件距离控件顶边的距离,即视图坐标
- getRawX(): 获取点击事件距离整个屏幕左边的距离,即绝对坐标
- getRawY(): 获取点击事件距离整个屏幕顶边的距离,即绝对坐标
onTouchEvent()
- 返回true表示处理触控,返回false表示不进行处理
对单点触控和多点触控进行处理
/* 如果return true,表示onTouchEvent处理完事件后消费了此次事件。此时事件终结;
*如果return fasle,则表示不响应事件,那么该事件将会不断向上层View的onTouchEvent方法传递
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_CANCEL:
break;
}
//多点触摸时使用
int masked = event.getActionMasked();
switch (masked) {
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_POINTER_UP:
break;
}
//手指落在控件上点的个数
int pointerCount = event.getPointerCount();
/**
* 点的坐标再当前控件的坐标系下,会根据当前view 的缩放比和旋转进行变化。。
*一般是以当前view 的左上角为0点
*/
//单点操控手指落在屏幕上的坐标
float x = event.getX();
float x1 = event.getX(0);//多点操控时第几个点的坐标
//获得屏幕上的绝对坐标值
float rawX = event.getRawX();
//手指在屏幕上点击的区域
float size = event.getSize();
float size1 = event.getSize(0);//多点
return super.onTouchEvent(event);
}
事件分发的方法
![事件分发流程](https://img-blog.csdn.net/20160806171230593)传递方式:
ViewGroup调用onInterceptTouchEvent方法查看时候是要拦截传递,
1. 如果拦截,然后调用onTouchEvent查看是否消费该事件
1. 如果消费直接在该viewGroup中处理触摸事件。
2. 如果不消费再查看子控件是否能够消费触摸事件。
2. 如果不拦截,直接去子控件查看是否能够消费触摸事件。
1. 如果能够消费,ViewGroup会将触摸事件传递给该控件。
2. 如果不能消费,onTouchEvent返回false。
dispatchTouchEvent方法
事件分发的调度,是否将触摸事件向下传递
返回值与onInterceptTouchEvent和onTouchEvent方法的返回值有关
/* * 返回true,表示该View内部消化掉了所有事件。
* 返回false,表示View内部只处理了ACTION_DOWN事件,事件继续传递,向上级ViewGroup传递。
* 注意View里面是没有onInterceptTouchEvent函数(你已经是最底层劳动人员了,你还能把任务分配给谁) */
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.d(TAG, "dispatchTouchEvent: " + event.getAction());
return super.dispatchTouchEvent(event);
}
- 返回值实例
onInterceptTouchEvent 返回true,onTouchEvent返回true
D/CustomViewGroupTestTouchEvent: dispatchTouchEvent: true
D/CustomViewGroupTestTouchEvent: dispatchTouchEvent: true
onInterceptTouchEvent 返回true,onTouchEvent返回true
onInterceptTouchEvent 返回true,onTouchEvent返回true
onInterceptTouchEvent 返回true,onTouchEvent返回true
onInterceptTouchEvent 返回true,onTouchEvent返回true
onInterceptTouchEvent 返回true,onTouchEvent返回true
onInterceptTouchEvent方法
需要自己处理触摸事件的时候返回true,自己不进行事件的吸收让子控件进行处理的话返回false
return true :表示将事件进行拦截,并将拦截到的事件交由本层控件 的 onTouchEvent 进行处理;
return false :则表示不对事件进行拦截,事件得以成功分发到子View。并由子View的dispatchTouchEvent进行处理。
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
}
return super.dispatchTouchEvent(event);
}
Android Scroll分析
view 的移动
- 示例:view的移动
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) event.getRawX();
int rawY = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastX = rawX;
mLastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
int offSerX = rawX - mLastX;
int offSetY = rawY - mLastY;
layout( getLeft()+offSerX,
getTop()+offSetY,
getRight()+offSerX,
getBottom()+offSetY);
mLastX = rawX;
mLastY = rawY;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
//API封装的移动方法,只需要计算出偏移量
offsetLeftAndRight(offSerX);
offsetTopAndBottom(offSetY);
view 的弹性滑动
- scrollTo
- scrollBy
按照下面的步骤进行
- 搞懂view的滑动原理
- 搞懂如何实现弹性滑动
- 搞懂view的滑动冲突
- 搞懂view的measure、layout和draw
- 然后再学习几个已有的自定义view的例子
- 最后就可以搞定自定义view了,所谓万变不离其宗