空手撸一个Android阅读器,无第三方支持

开篇


几个月前,晚上梦到在研究翻页动画,次日上班居然想起了昨天晚上的梦。search了相关信息,大概要用到数学计算、canvas绘图等相关内容。对我来说手动绘图这方面的实践还是0,想想短时间内应该搞不定,便将此事记在了待做清单内。(公司电脑一个单子,自己Mac一个单子,增加行数的速度远比删除的速度快。)

十一长假前夕手头没什么事情,看着清单顶部的第一项(时间排序),便照着例文开始绘图。画到后面,想想就一张图片多无聊。算了!加点功能做个带翻页动画的阅读器吧!

preview1
preview2
preview3

项目地址:GitHub
觉得好的话star一下

文章顺序:

  • 翻页
  • 内容
  • 工具栏

翻页

主要是按照
Android自定义View——从零开始实现书籍翻页效果
的逻辑,自己手敲了一遍完成的翻页动画,并对代码进行了调整。
期间也学习了
各个击破搞明白PorterDuff.Mode
一起看画布Android Canvas
对代码理解和调整起到了很大帮助。

这里就不赘述以上文章的内容,直接说明调整后的代码逻辑。

自定义控件继承自View,通过重写

  • onMeasure 来获取控件的宽高,取得纸张各点的初始值
  • onDraw 用来绘制纸张、阴影、内容
  • onTouchEvent 获取用户的手势事件,重计算各点并绘制,达到翻页的动效
  • computeScroll 用到了Scroller,来执行手势事件后的翻页、恢复效果

初始化

因为视图是通过Canvas绘制出来的,因此控件初始化时要将

  • Point 书页运动的关键点,用于完成翻页动画
  • Paint 内容画笔
  • Path A、B、C区域的路径,用于翻页时路径的裁剪
  • Gradient 阴影

初始化,并打开setClickable(true),用以接收手势事件

测量

按View的生命周期,到了onMeasure

设置BookPageView的宽高后,便有了关键点的初始值。通过宽高值,初始化A、B两个不同区域的Bitmap。

绘制

具备了Point、Paint、Path、Gradient、Bitmap,便可以开始绘制Canvas。

将准备好的纸图片,绘制到Canvas当全局背景,用以填充裁剪所漏出的区域。

具体的绘制过程需要根据翻页的方向进行区分,因为翻页的方向不同,导致各关键点的计算公式、阴影位置不同。

触点

区域划分

ACTION_DOWN时判断翻页的位置,预先加载前一页or后一页的内容到Bitmap上,并计算各点坐标。

正常状况下滑动不予翻页,避免突兀到翻页效果。

翻页结束,根据预设条件判断翻页还是恢复,并调用Scroller.startScroll。

内容

由于翻页相关的内容主体逻辑已经在引用中有了详细的解释,所以没必要用篇幅再去讲解一遍。

但内容相关的代码会详细介绍,涉及到字体大小所影响的页面显示、TXT内容的读取策略等

根据最少知识原则设计内部类ContentController,用以读取文件、缓存内容、获取当前内容。

根据TXT小说的大体估计,平均一行约500汉字,共占1000字节约1K。

每页约1~3行,由每行字数多少决定。

缓存策略为缓存50页:当前页的前10页、包括当前页的后40页。

获取指定页内容(待优化)

从缓存中取,若指定页为阀值,则更新缓存。

待优化点:

  • 未预先缓存数据,现在显示正常是因为onMeasure的多次执行,导致initBitmapA多次执行,从而代替了预先缓存。如果内容不变的话initBitmapA不应该多次执行。

更新指定页前后的内容(待优化)

根据当前页计算,需缓存的前后页码。

待优化点:

  • 重复内容并没有重用,(现缓存1~50,需缓存37~87,则37~50内容重复)。但限于读取的方式,暂没想到好的解决办法,见下。

获取指定范围的内容(重点)

初始数组,获取输入流

标记第一页,根据字体大小计算每页及每行可容纳的字数。

标准IO操作,读取每行内容,计算当前行长度+当前页内容长度,是否超过当页容量,超过则放到下一页。当这页已满,stringBuffer.toString()放入result数组,页数加一。

由于每次读取都是从第1页开始,若缓存30~80页,则先读取前30页的内容并抛弃,然后才存到数组缓存。

所以要判断

待优化点:

  • 现读取的是raw中的文件,可优化选择文件功能
  • 每次读文件都是从第一行开始读,读字节的话又会造成,前后页之间的文字乱码。(暂未想到解决办法)
  • 当一页的第一行只有1个或很少的字数并换行,且接下来的段落每行字数都很满,则会造成最后一行绘出屏幕

工具栏

一个完整的书页,需要有工具栏来设置字体、字号、背景色等多种功能。这里只提供了工具栏,至于具体的工具待填充。

由于没有工具,所以


这里完全可以如上所说代码布局,我省个事!!

在onFinishInflate,获取对应控件。不必担心回调优先执行导致控件空指针,此处控件已初始化完成,并setText,在onMeasure和onLayout中也只会对控件进行拉伸显示

对控件进行测量,切记注意EXACTLY、AT_MOST与实际xml中填写项的对应。

这里布局子View,需要注意layout时,不要只在乎左上角的点,右下角同样重要,否则控件会被拉伸。

动画效果采用了Animator,属性动画,通过改变自定义属性,不停的layout达到效果

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,463评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,868评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,213评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,666评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,759评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,725评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,716评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,484评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,928评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,233评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,393评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,073评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,718评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,308评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,538评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,338评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,260评论 2 352

推荐阅读更多精彩内容