【android】如何实现猿题库题目的排版

时间:2024-10-13 19:07:02

最近我们的产品来了个新的模块,类似猿题库一样,给学生做题提高成绩的。

要求如下:

1:支持单选、多选、填空题

2:支持图片文字混排

3:输入框有交互,排版精致美观

4:为了体验优化,不能使用网页实现效果

花了两个礼拜开发优化,效果看起来达到了猿题库那种图文、输入框混排的效果,截图如下:

【android】如何实现猿题库题目的排版 【android】如何实现猿题库题目的排版 【android】如何实现猿题库题目的排版

因涉及到公司的核心业务,就不分享源码了,讲解下大概实现步骤

1:图片文字混排

系统的TextView通过ImageGetter就可以原生实现对文本img标签的支持,从而达到图文混排的效果。

Html.fromHtml(text, asyncImageGetter, null);

具体实现步骤请参考Github上的一个库https://github.com/zzhoujay/RichText

2:输入框混排

如何实现一个自己的TextView,请参考此篇博客http://blog.****.net/yellowcath/article/details/27527275

下面是我具体的实现步骤,请在步骤1图文混排源码基础上进行阅读。

最后的UI结构应该是这样子的,用输入框盖在透明的占位图上,达到了输入框混排的效果。

--容器

--图文混排TextView

--输入框A

--输入框B

--输入框C

2.0:根据题目答案数量,生成对应数量的输入框,添加到容器中,设置为不可见

2.1:题目中的输入框标记,通过正则表达式使用图片Img标签代替,src设置为:Input标签+输入框对应答案ID+该输入框对应答案文字长度

2.2:在ImageGetter中,发现当前图片包含Input标签,则使用一个透明的占位图代替,宽度为画笔的文本尺寸*答案长度

2.3:参考本步骤开始给出的代码地址,稍微加工下就可以拿来实现自己的TextView,用于逐行绘制时,获取当前的宽度和高度。

2.4:在onDraw事件里,遇到当前绘制的Span是图片类型,且src包含Input标签的,获取当前的高度和左边距,通过下面代码获取图片的宽度。

imgSpan.getDrawable().getBounds().width()

2.5:用步骤4取到的数据,设置MarginLeft和MarginTop,还有宽度,通过输入框对应答案ID来找到2.0对应的输入框,刷新其位置和宽度

3:细节优化

1:填空题的行高比选择题的要大,为了防止两行文本框挤在一起。

2:输入框UI有很多状态:做题状态:未获取焦点没值、未获取焦点有值、获取焦点;校对答案: 答案正确、答案错误

3:输入框超过答案的长度,使用省略号...截取掉超过的文本。

4:图片、输入框长度最长为一行,超过图片等比缩放。

5:图片添加缓存,加载中给占位图,加载失败点击重试(文本框里的图片是可以响应点击事件的,详情参考步骤1的源码)

6:某行有大图的情况下,文本、输入框垂直居中显示;反之如果图片是小图(数理化公式类型),则垂直居中显示

7:使用FragmentStatePagerAdapter 代替 FragmentPagerAdapter作为大批量内容页的适配器。

8:在开始答题的时候,我们已经获取到了此次所需的题目和答案数据,正则匹配出里面的图片url,在后台提前下载好到内存中。

后记

一开始遇到图文输入框混排,不能用WebView,立刻百度

结果这个需求愿意分享的人很少,无奈之下只能自己一步一坑解决了。

下载猿题库的apk包,反编译,结果看花眼了也跟踪不到题库的相关代码。

倒是在开启了布局边界之后,在仔细观察猿题库的题目时,发现填空题很多地方,绘制是重叠的,得出其原理是设置输入框位置来实现的结论。

还好有上面两个开源的作品,在次基础上进行开发,有思路多了。

比较奇怪的是,猿题库ViewPager频繁切换的时候,是会有延迟的。

我们这个一旦打开就立刻呈现在用户面前,图片加载完成之后,再刷新占位图,个人觉得这样过程要好点。

欢迎大家一起交流,有啥疑问的请留言。