这段时间在项目中遇到一个问题,就是超长的 Path 在自定义 View 中无法绘制的,这个问题虽然少见,但是确实很恶心,具体的原因我们也知道,是因为 Android 在4.0以上默认开启了硬件加速,虽然可以加快 View 的绘制提升流畅度,但是也会导致一些绘制函数无法正常工作,当然关闭硬件加速可以解决问题,但是你会发现自定义的 View 会卡顿的不行。
解决思路一
既然 Path 太长,那我们就想办法把这个 Path在屏幕中显示的内容截取出来再去绘制,具体的工具类系统源码也有提供(PathMeasure),这个类最主要用到的功能就是他可以根据曲线上一点到起点的距离,得到该点的具体坐标,而且可以根据一段距离截取一个路径,具体的作用大家可以参考源码(大家最好先看一下这个类的使用方式,因为他是实现截取的关键)。
分析一下,Path 路径和屏幕的交汇情况大概如上图(其中曲线为 Path,方块为屏幕)。我们只需要粗率截取被屏幕包裹的路径,即这个被截取出来的路径即要被屏幕包围也要尽可能小(就是这个截取出来的路径可以比屏幕略大一点,从而保证用户看到的界面是对的)。
对于 B,C 情况,我们很容易得到首尾坐标和距离,并以一定的步长去扩展路径,直到找到被屏幕截取的径长度范围,从而截取我们想要的部分 Path。
但是对 A 情况,我们必须找到一个在屏幕范围内且在曲线上的点,作为相对起点,然后以该点的距离向上向下扩展路径,从而找出我们需要被截取的范围。
那么找到这个相对起点就成了主要问题。首先可以排除的是遍历方法(因为是屏幕绘制相关的问题,所以耗时问题是必须考虑的)。起初我考虑的是利用二分法,将问题简化为找到离屏幕方块最近的曲线上的点,但是后来发现因为我的项目中屏幕和曲线的相对位置,相对大小都是随机的,需要考虑的情况太多太复杂,所以智能放弃这个方法。。。但是如果大家的问题没有我的这么复杂可以考虑这么做。
解决思路二
当我的一个朋友告诉我把路径分为一百份,逐份遍历每一块去寻找屏幕应该截取的曲线范围,我就蒙逼了,我才发现我钻了牛角尖,这个方法遍历次数少到几乎可以忽略,而且经过简单的优化可以很完美的把路径切分开,问题迎刃而解...
总结
这次问题的解决虽然之前钻了牛角尖,但是我也尝试了更多的解决思路,在一次次问题碰壁中成长,另外感谢这位非相关专业的朋友一语点醒梦中人,不然我可能还需要钻几天的牛角尖...