ViewGroup也是View,所以接下来看View的dispatchTouchEvent():
第二个条件是判断当前点击的空间是否为enable,但由于基本View都是enable的,所以这个条件基本返回true;
第三个条件表示我们调用setOnTouchListener时必须覆盖onTouch()的返回值。
可见onTouch()方法的优先级高于onTouchEvent()。
- onTouchEvent()
可以看到只要View的CLICKABLE和LONG_CLICKABLE有一个为true,那么onTouchEvent()就会返回true消耗这个事件。我们通常用setOnClickListener和setOnLongClickListener来设置被点击和长按。
接着看下performClick()方法:
可以看到,如果MOnClickListener不为空,那么它的onClick()方法就会调用。
- onInterceptTouchEvent()
view绘制流程和原理:
窗口和view和activity的区别:https://www.jianshu.com/p/28d396a0f05f
GestureDetector:在onTouchEvent(MotionEvent event) 中回调scaleGestureDetector.onTouchEvent(event),判断滑动还是缩放区分手指就好
SurfaceView:
demo3:使用的ViewPager,并设置PagerAdapter。
demo5:
ScaleGestureDetector:缩放
mGesture = new ScaleGestureDetector(mContext, new ScaleGestureDetector.OnScaleGestureListener() {
//随着手势操作,回调的方法,
@Override
public boolean onScale(ScaleGestureDetector detector) {
float previousSpan = detector.getPreviousSpan();//缩放发生前的两点距离
float currentSpan = detector.getCurrentSpan();//缩放发生时的两点距离
if (previousSpan < currentSpan)//放大
{
mZoomScale = mZoomScale + (currentSpan - previousSpan) / previousSpan;
} else {
mZoomScale = mZoomScale - (previousSpan - currentSpan) / previousSpan;
}
//确保放大最多为2倍,最少不能小于原图
if (mZoomScale > 2) {
mZoomScale = 2;
} else if (mZoomScale < 1) {
mZoomScale = 1;
}
setScaleX(mZoomScale);
setScaleY(mZoomScale);
//这里调用的是本自定义View的方法,是对本自定义view进行的缩放
/*在这里调用getChildView(index)的进行缩放,虽然控件显示大小改变了,
但是在ViewDragHelper的回调方法中获得的View child的getWidth()和getHeigit()是原来的大小,不会发生改变*/
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
});
ViewDragHelper控制子view的移动:
mViewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
//这里的return true表示自view可以滑动,false表示不处理滑动
return true;
}
/这里是控制子view左右滑动的回调,child为本自定义view的子控件,left表示意图从手指操作子view从左边界滑动的距离,大于0表示向右移动,小于0表示向左移动,是从手指的移动测出的理论值。方法的返回值表示实际上控件移动的距离,可以用返回值控制边界/
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
//放大后控件的宽度-主布局的宽度 因为View chlid的控件使用的是match_parent,所以直接用父布局的宽取值
if (left < (getWidth() - getWidth() * mZoomScale) / 2) {
return (int) ((getWidth() - getWidth() * mZoomScale) / 2);
}
if (left > ((mZoomScale * getWidth() - getWidth()) / 2)) {
return (int) ((mZoomScale * getWidth() - getWidth()) / 2);
}
return left;
/** 这里进行边界处理,因为这里实际最大能放大2倍,那么实际会有3/4的左右滑动空间才会把子View(child)完全划出可见范围,这里为了保证view的可见性,使用1/2确保子view始终在可见范围之内*/
}
/这个方法是控制上下滑动的,跟上面的方法意义一样,只是方向上不一样,top表示从顶部边界计算的距离,向下为正,向上为负/
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
最后是今天给大家分享的一些独家干货:
【Android开发核心知识点笔记】
【Android思维脑图(技能树)】
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【Android高级架构视频学习资源】
参考docs.qq.com/doc/DSkNLaERkbnFoS0ZF
2604243)]
【Android思维脑图(技能树)】
[外链图片转存中…(img-mYkctIG8-1724392604244)]
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
[外链图片转存中…(img-AMlQrGLK-1724392604244)]
【Android高级架构视频学习资源】
参考docs.qq.com/doc/DSkNLaERkbnFoS0ZF