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

起因

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

  • https://github.com/Frank-Zhu/PullZoomView

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

  • https://github.com/Gnod/ParallaxListView

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

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

PullToZoomScrollView

下面主要说明下,我在修复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这个问题。

总结

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

转载请注明出处

http://www.cnblogs.com/gaoteng/p/5485634.html

http://www.gaotenglife.com/?p=382

android一个下拉放大库bug的解决过程及思考的更多相关文章

  1. Android-PullToRefresh下拉刷新库基本用法

    How:(使用) 转自:http://blog.csdn.net/hantangsongming/article/details/42490277 PullToRefresh是一套实现非常好的下拉刷新 ...

  2. Xamarin. Android实现下拉刷新功能

    PS:发现文章被其他网站或者博客抓取后发表为原创了,给图片加了个水印 下拉刷新功能在安卓和iOS中非常常见,一般实现这样的功能都是直接使用第三方的库,网上能找到很多这样的开源库.然而在Xamarin. ...

  3. Android智能下拉刷新加载框架—看这些就够了

    一些值得学习的几个下拉刷新上拉加载开源库 Android智能下拉刷新框架-SmartRefreshLayout 支持所有的 View(AbsListView.RecyclerView.WebView. ...

  4. Android原生下拉刷新SwipeRefreshLayout实践

    本篇文章翻译自Ravi Tamada的Android Swipe Down to Refresh ListView Tutorial 首先来看一下效果图 你应该发现很多的android app比如Tw ...

  5. IOS下拉放大图片

    代码地址如下:http://www.demodashi.com/demo/11623.html 一.实现效果图 现在越来越多的APP中存在下拉放大图片的效果,今天贡献一下我的实现这种方法的原理,和我遇 ...

  6. Android SwipeRefreshLayout 下拉刷新——Hi_博客 Android App 开发笔记

    以前写下拉刷新 感觉好费劲,要判断ListView是否滚到顶部,还要加载头布局,还要控制 头布局的状态,等等一大堆.感觉麻烦死了.今天学习了SwipeRefreshLayout 的用法,来分享一下,有 ...

  7. Android 自定义下拉刷新ListView

    package com.dwtedx.qq.view; import android.content.Context; import android.util.AttributeSet; import ...

  8. android实现下拉框(spinner),自己定义大小颜色背景位置,去掉默认样式黑边

    1. 实现最简单的spinner xml文件,有一个TextView,一个Spinner: <RelativeLayout xmlns:android="http://schemas. ...

  9. Android Spinner 下拉框简单应用 详细注解

    目录 Android Spinner 代码部分 Spinner代码介绍 核心代码 说在最后 @ Android Spinner Spinner 提供下拉列表式的输入方式,该方法可以有效节省手机屏幕上的 ...

随机推荐

  1. 安装PHPphp-5.4.4

    一.下载PHPphp-5.4.4 [root@aliyun software]# pwd /software[root@aliyun software]# wget http://mirrors.so ...

  2. Python学习---Model拾遗[1]180318

    Model: 强大的数据库操作,弱小的数据验证 Form:  强大的数据验证 ModelForm: 强大的数据验证 + 弱小的数据库操作 Model拾遗 Model基本操作 1. 创建数据库表2. 修 ...

  3. December 20th 2016 Week 52nd Tuesday

    With the wonder of your love, the sun above always shines. 拥有你美丽的爱情,太阳就永远明媚. To accept the love from ...

  4. Git 解决方案 commit your changes or stash them before you can merge

    error: Your local changes to the following files would be overwritten by merge: *********** Please, ...

  5. Linux文件系统知识记录——ext2描述

    最近完成了一个编程作业,大致功能是给定一个文件名,给出该文件所在目录和其本身所占用的簇号等信息.笔者选用了Linux的ext系列文件系统作为实验对象,通过实验对ext2文件系统的存储和索引有了一个较为 ...

  6. Linux系统下常用的磁盘管理命令——du / df / fdisk / mount / xxd

    之前使用虚拟机体验Linux操作系统的使用,一般使用默认的磁盘分区设置,也很少涉及磁盘管理操作,且总有删除重装作为后盾.在安装Ubuntu双系统后,在使用过程中遇到了磁盘分区不合理导致的/boot分区 ...

  7. psql: FATAL: role “postgres” does not exist

    I'm a postgres novice. I installed the postgres.app for mac. I was playing around with the psql comm ...

  8. pop链构造

    class Person { private $name; private $sex; private $age; //__set()方法用来设置私有属性 function __set($proper ...

  9. Python 模块化 自定义模块 (四)

    自定义模块 一个.py文件就是一个模块 创建以下三个文件: 运行test.py ,查看运行结果. #test.py print("this is test module") imp ...

  10. 深入学习c++--重新审视auto

    1. auto推断变量类型 2. auto遍历 3. 自定义类可使用auto