最近项目主要是做一个类似wps文档阅历的功能,以列表的形式显示文档,并且需要实现缩放平移。而网上关于此类功能的实现主要是通过自定义的listview实现的,类名为ZoomListView。

网上的zoomlistview模板大多是一套,主要核心代码就是以下:

 @Override
protected void dispatchDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
if (mScaleFactor == 1.0f) {
mPosX = 0.0f;
mPosY = 0.0f;
}
canvas.translate(mPosX, mPosY);
canvas.scale(mScaleFactor, mScaleFactor);
super.dispatchDraw(canvas);
canvas.restore();
invalidate();
}

该函数主要实现了对整体列表的缩放和平移。但是mPosY的值影响了判断当前显示的第一个item,而且当你惯性滑动时,永远滑不到底。所以如何解决这两个问题呢。

解决第一个问题很简单,canvas.translate(mPosX,0),就可以了。而此时由于没有了纵向的平移,列表肯定会显示不全了。

如何解决列表显示不全的问题呢。究其原因是因为滚动条滚不到底的原因。由于此时网上也没有这方面的资料,写ZoomListView的大佬也找不到本人,后来的人估计也是copy然后写文章的,问他们其实也都不知道。于是我决定自己看源码解决问题。

根据代码跟踪发现了滚动的时候会调用trackMotionScroll函数,其中有这么一串代码:

        final boolean cannotScrollDown = (firstPosition == 0 &&
firstTop >= listPadding.top && incrementalDeltaY >= 0);
final boolean cannotScrollUp = (firstPosition + childCount == mItemCount &&
lastBottom <= getHeight() - listPadding.bottom && incrementalDeltaY <= 0); if (cannotScrollDown || cannotScrollUp) {
return incrementalDeltaY != 0;
}

其中cannotScrollUp就是不能向下滚动。看这个式子有没有发现什么问题,判断不能向下滚动的条件是lastBottom <= getHeight() - listPadding.botoom。于是我突发奇想设置paddingbottom的值就好了。设置paddingbottom为对应值后,发现真的可以滚动了,太棒了,问题基本上解决了。

后来发现又有bug了,在paddingbottom部分居然不能滚动!不能滚动!不能滚动!!!哎,详细也正常,padingbottom本来就是不能滚动的,这时候怎么办呢。然后调试进入ontouchevent函数中,发现触摸该区域其实还是可以会调touchevent事件的。于是我有想到了一个奇妙的方法去解决问题。自己在touchevent中先对ev的y值进行位移,这样该区域就可以滚动了。

终于解决问题了,经过这一次我明白了一个道理,当你遇到问题的时候,一定要解析问题所在,然后跟踪深入源码,只有知道底层代码才能更好的解决问题。

想要源码的可以评论,在这里就不贴了。

这几天又来了一个需求,如何保证中心缩放。这个就有点难了,如何在这个类上修改呢。第一步就是需要优化在双指缩放的时候不能平移画布。这个问题横向的时候好解决,只要判断是否是单指就行了。横向的时候就需要禁用滚动来判断,函数setenable。

第二步就是找推导公式,进行算出新的平移。以下是纵向调整平移的代码。

            //求y0的推导公式,view是对应中心点item的view。
/*
(view.top + y0)*mOldScaleFactor = cy;
(view.top(新)+y0)*mScaleFactor = cy;
先求出view.top(新),然后计算出view.top(新)与view.top之间的差。
然后求得firstitem的view.top(新的值),最后通过setSelectionFromTop滚动到对应区域
*/
int iFirstItem = getFirstVisiblePosition();
int iFirstViewTop = 0;
for(int iCnt=0;iCnt<getChildCount();++iCnt)
{
View view = getChildAt(iCnt);
if(0==iCnt)
{
iFirstViewTop = view.getTop();
}
int iViewTop = (int)(view.getTop()*mOldScaleFactor);
int iViewBottom = (int)(view.getBottom()*mOldScaleFactor);
if(iViewTop<=cy && cy<=iViewBottom)
{
int iNewViewTop = (int)(cy/mScaleFactor - (cy/mOldScaleFactor-iViewTop));
int iNewFirstViewTop = iFirstViewTop + (iNewViewTop-iViewTop);
if(0==iFirstItem && iNewFirstViewTop>=0)
{
iNewFirstViewTop = 0;
}
setSelectionFromTop(iFirstItem,iNewFirstViewTop);
break;
}
}

主要要算出当前点会平移多少,然后通过setSelectionFromTop来校准。终于经过千辛万苦,把缩放的listview完成的总算可以了!!!

浅谈网上的zoomlistview存在的问题的更多相关文章

  1. iOS开发之浅谈MVVM的架构设计与团队协作

    今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...

  2. Android应用安全开发之浅谈加密算法的坑

      <Android应用安全开发之浅谈加密算法的坑> 作者:阿里移动安全@伊樵,@舟海 阿里聚安全,一站式解决应用开发安全问题     Android开发中,难免会遇到需要加解密一些数据内 ...

  3. 浅谈php生成静态页面

    一.引 言 在速度上,静态页面要比动态页面的比方php快很多,这是毫无疑问的,但是由于静态页面的灵活性较差,如果不借助数据库或其他的设备保存相关信息的话,整体的管理上比较繁琐,比方修改编辑.比方阅读权 ...

  4. 浅谈HTTPS以及Fiddler抓取HTTPS协议

    最近想尝试基于Fiddler的录制功能做一些接口的获取和处理工作,碰到的一个问题就是简单连接Fiddler只能抓取HTTP协议,关键的登录请求等HTTPS协议都没有捕捉到,所以想让Fiddler能够同 ...

  5. 浅谈struts2之chain

    转自:http://blog.csdn.net/randomnet/article/details/8656759 前一段时间,有关chain的机制着实困绕了许久.尽管网上有许多关于chain的解说, ...

  6. Android性能优化的浅谈

    一.概要: 本文主要以Android的渲染机制.UI优化.多线程的处理.缓存处理.电量优化以及代码规范等几方面来简述Android的性能优化 二.渲染机制的优化: 大多数用户感知到的卡顿等性能问题的最 ...

  7. 【转】 浅谈Radius协议

    浅谈Radius协议 2013-12-03 16:06 5791人阅读 评论(0) 收藏 举报  分类: Radius协议分析(6)  从事Radius协议开发有段时间了,小弟不怕才疏学浅,卖弄一下, ...

  8. 转:浅谈Radius协议 -来自CSDN:http://blog.csdn.net/wangpengqi/article/details/17097221

    浅谈Radius协议 2013-12-03 16:06 5791人阅读 评论(0) 收藏 举报  分类: Radius协议分析(6)  从事Radius协议开发有段时间了,小弟不怕才疏学浅,卖弄一下, ...

  9. 【转】Android Canvas的save(),saveLayer()和restore()浅谈

    Android Canvas的save(),saveLayer()和restore()浅谈 时间:2014-12-04 19:35:22      阅读:1445      评论:0      收藏: ...

随机推荐

  1. 嵌入式开发之davinci--- DVRRDK, EZSDK和DVSDK这三者有什么区别

    下载的时候选择信息要避免security类型的产品,这个是要审查的. DVRRDK是专门针对DVR的开发包是非公开的,针对安防的客户定制的,效率要高. EZSDK是开放的版本架构上使用openmax可 ...

  2. sizeof、strlen

    一.sizeof sizeof(...)是运算符,sizeof操作符的结果类型是size_t.它在头文件里typedef为unsigned int类型.是以字节为单位进行计数的.所以位域成员不 能用s ...

  3. sql里的in对应linq的写法 及 IQueryable转化为Dictionary

    string[] arID = { "0001", "0002" }; var dict = this.service.GetMyList(m => ar ...

  4. Entity FramWork Code first 使用心得

    1 最有用的命令 update-database -force -verbose 2 主键如果不是默认的int或者 bigint而是guid 或者 string类型,创建记录的时候要给主键赋值 3 在 ...

  5. SQL语句--常用

    一.基础 1.说明:创建数据库CREATE DATABASE database-name 2.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备 ...

  6. Lightoj 1006 Hex-a-bonacci

    Given a code (not optimized), and necessary inputs, you have to find the output of the code for the ...

  7. Lightoj 1009 - Back to Underworld

    1009 - Back to Underworld    PDF (English) Statistics Forum Time Limit: 4 second(s) Memory Limit: 32 ...

  8. yii2.0 ActiveRecord 查询汇总

    User::find()->all(); 此方法返回所有数据: User::findOne($id); 此方法返回 主键 id=1 的一条数据(举个例子): User::find()->w ...

  9. 洛谷P1527 矩阵乘法——二维树状数组+整体二分

    题目:https://www.luogu.org/problemnew/show/P1527 整体二分,先把所有询问都存下来: 然后二分一个值,小于它的加到二维树状数组的前缀和里,判断一遍所有询问,就 ...

  10. 查看html元素绑定的事件与方法 visual Event 插件

    WEB标准提倡结构.表现和行为相 分离,现在越来越多采用这种表现和行为的方式,但它也为我们开发调试带来一些问题,网页载入一堆JavaScript,,我们很难搞清楚最后在哪些元素的哪个动作绑定了事件,尤 ...