Android高仿qq阅读/微信读书/掌阅高亮选择文字效果

前言

   最近做epub阅读器,有划线的需求,即类似于qq阅读/微信读书/掌阅那样的移动选择文字并高亮划线等,在这里记录下实现的思路供大家参考,功能都还没有上线,等优化彻底了,我可以考虑抽出这个模块开源下,嘿嘿!

实现的效果图

可以看到,这个效果还是可以的,目前来说,我是将这个移动选择绘制在文字的上层,即盖一个颜色的透明层,最好的移动绘制是在文字的下方绘制,这样文字的颜色不会因为绘制而模糊改变,微信读书/掌阅是绘制在下方的,qq阅读应该和我的实现方法类似,在文字的上层绘制,绘制的颜色带点透明度,不过我文字的底部划线必须和文字在一个canvas画布上,否则你移动的时候,会发现划线和文字不是同时移动,就是因为不在同一个canvas上的问题.

主要实现步骤

 

 阅读器实现原理

  阅读器每个页面其实是由底层C++(编写对应so库)绘制文字并生成一个图片供java上层调用,所以说,这些页面本身是一张图片bitmap,其实我们就是在这个bitmap上做文章,比如绘制文章章节的头部信息,底部页码信息,长按移动选择文字等.目前市面上的阅读器应该都是这个实现的思路,即底层绘制,分页提供so库供上层调用显示.

 页面信息

   虽然底层返回的是一张图片给上层,但是每个页面所包含的文字信息(包括文字的坐标,文字内容,段落ID等)都会返回给上层,我门根据坐标绘制即可.

 ios文字坐标计算:直接使用改坐标x,y即可;安卓我的算法目前是这样的:x * density,y * density 即乘以屏幕的密度,按道理说最好直接使用底层提供的x,y,后续这块还可以优化,这块主要是底层的坐标计算问题,目前乘以屏幕的密度,可以准确定位到当前文字的位置,无论文字怎么放大缩小,划线均可以准确的显示到该文字的下方,毕竟是根据坐标来划线的.

 有了文字的x,y位置坐标,其实绘制就简单多了,当前选中的区域是一段段Rect区域,使用path 动态的将他们联系在一起即可.

比如文字F的rect区域 RectF rect = new RectF(F.x,F.y,F.x + F.Width,F.y + F.Height);//注意x,y乘以屏幕的密度

 文字rectF核心代码,movey + 1是为了减少高度误差,即增加了rectF区域的高度.

 private RectF createRectF(int startX, int startY, int moveX, int moveY) {
        return new RectF(startX * mDensity, startY * mDensity, moveX * mDensity, (moveY + 1) * mDensity);
    }

 手指移动绘制就是根据选中的首尾两个字符,进行循环遍历绘制.(当前页面的所有文字信息遍历)

 绘制相对来说,不是特别难的,难度最大的属于划线,还有合并划线的功能,下面也给大家提供点实现思路.

难点

合并划线功能,即判断两条线是否有交集等.这里给大家个思路.

分三种情况:

1.划线区域包括了选择区域(这个场景可以直接不做任何操作,或者进行取消划线的操作)

2.选择区域包括划线.

3.选择区域和划线有交集(前后交集)

 这个功能写了一周,确实很麻烦,只能根据页面提供的文字坐标等信息进行遍历计算判断.

总结

上面说了下这个阅读器文字选择和划线的实现的思路,功能还需完善,还未上线,暂时也无法开源,大家有问题可以留言给我,我有看到,会及时回复!

 其实这个功能不是特别的难,相信大家花点时间也都会做出来的!

发布了60 篇原创文章 · 获赞 109 · 访问量 36万+

猜你喜欢

转载自blog.csdn.net/shenshibaoma/article/details/80594222