安卓吸顶+下拉放大_android一个下拉放大库bug的解决过程及思考

android一个下拉放大库bug的解决过程及思考

起因

项目中要做一个下拉缩放图片的效果,搜索了下github上面,找到了两个方案。

这个库本来做的还可以,不过有个缺陷就是,当scroolview滑动到底部,再向上拉动,会导致放大效果不连续,需要重新释放,再次下拉,这对于追求细节的我来说,不可忍受。看了半天他的代码,感觉他的实现方式很难修改为我想要的效果,后来就放弃了。

这个自定义view写的笔记简单,也很容易看懂,同时避免了上面那个库的问题,所以通过简单的改造,我修改成为ScrollView的方式。但是同时也碰到一个问题,那就是当ScrollView中包含的view设置了OnClickListner事件的时候,触摸事件的传递会出现问题。导致滑动出现异常。

下面就是我修改后的项目地址

下面主要说明下,我在修复bug的时候的思路。

首先看下具体问题:

当scrollview 中的元素未占满scrollview的时候,在scrollivew的onInterceptTouchEvent方法中

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

//中间代码省略

/*

* Don't try to intercept touch if we can't scroll anyway.

*/

if (getScrollY() == 0 && !canScrollVertically(1)) {

return false;

}

//中间代码省略

}

有一个canScrollVertically的判断,用来返回scrollview的内容是否撑满,所以当scrollview中的元素未占满的时候,这里直接返回false,scrollview的触摸事件没有截获,直接交给了子view处理,而这个时候,子view又设置了click事件,对触摸进行了消费,所以scrollivew无法响应下拉的手势操作了。

解决思路

对于这种触摸冲突的问题,之前看《android艺术开发探索》时候,有过了解,无非就是两个,一个外部拦截,一个内部拦截。想到scrollview中的元素可能会嵌套很多类型的。所以内部拦截的方式,可能工作量很大,需要每个View做处理。所以初步锁定了外部拦截方式。

刚开始的思路也很清晰,就是当向下滑动的距离大于了TouchSlop时候,就截获事件,不向下传递,如果是点击的时候,则直接传递到下面的view进行处理。

@Override

public boolean onInterceptTouchEvent(MotionEvent event) {

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

xFirst = event.getX();

yFirst = event.getY();

mIsIntercept = false;

case MotionEvent.ACTION_MOVE:

xDistance = event.getX()-xFirst;

yDistance = event.getY()-yFirst;

if(Math.abs(yDistance)>mTouchSlop){

mIsIntercept = true;

}else {

mIsIntercept = false;

}

break;

case MotionEvent.ACTION_UP:

mIsIntercept = false;

break;

default:

break;

}

return mIsIntercept;

}

@Override

public boolean canScrollVertically(int direction) {

return true;

}

可是当这样写之后,总是会抛一个错误,Invalid pointerId=-1 in onTouchEvent,到源码里面看,这个错是

@Override

public boolean onTouchEvent(MotionEvent event) {

Log.e("scrollview",event.getAction()+"");

touchListener.onTouchEvent(event);

return super.onTouchEvent(event);

}

是调用super.onTouchEvent(event)的时候抛出来的,再次查看源码,原来是scrollview里面的一个变量没有赋值,原本的赋值操作是在onInterceptTouchEvent中,但是这个函数已经被我们重写,那怎么办呢。后来想到,假如我在ACTION_DWON里面,先调用下surper.onInterceptTouchEvent(event),将变量赋值,那不就ok了,所以最后的代码结果是

@Override

public boolean onInterceptTouchEvent(MotionEvent event) {

switch (event.getAction()){

case MotionEvent.ACTION_DOWN:

xFirst = event.getX();

yFirst = event.getY();

mIsIntercept = false;

//这句话是关键

super.onInterceptTouchEvent(event);

case MotionEvent.ACTION_MOVE:

xDistance = event.getX()-xFirst;

yDistance = event.getY()-yFirst;

if(Math.abs(yDistance)>mTouchSlop){

mIsIntercept = true;

}else {

mIsIntercept = false;

}

break;

case MotionEvent.ACTION_UP:

mIsIntercept = false;

break;

default:

break;

}

return mIsIntercept;

}

@Override

public boolean canScrollVertically(int direction) {

return true;

}

同时我们也将canScrollVertically这个函数直接返回true,即不让super.onInterceptTouchEvent(event);调用的时候直接返回false

这样我就完美的解决了事件的分发处理与Invalid pointerId=-1 in onTouchEvent这个问题。

总结

上述的问题,大概经过了两天的各种尝试,才得到结果。而且灵感是在回家之后,不经意的一个瞬间,想到的,所以有时候,遇到问题,自己可以暂时先放一放,换个时间思维角度也许就大不一样,问题也就迎刃而解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值