打造原生的图文混排控件
随着互联网的发展,信息展示的元素越来越丰富,无论是PC端,还是移动端,图文混排已经成为一种通用的信息展示方式,但在各个平台却都没有提供这种原生的控件。为了更方便地在开发中展示丰富的文本信息,便自定义了这个图文混排控件。
思想
普通的图文混排,无非就两种元素:文字和图片。根据这种特点,我们可以自定义协议,如图片的的网址以\img_url\来引用。根据这种协议就可以将整个文章进行分段,然后动态地创建控件(TextView和ImageView)加载数据即可。
协议
文本不需要协议规定,图片网址用\img_url\的形式引用(协议自己定义)。
PS:对于文章中文字部分的或要做特殊处理。
实现
根据上面的思想,将很容易实现原生的图片混排控件,我们只需要自定义一个LinearLayout, 在其中动态加载布局即可。
step1: 将文章进行分段
没错,使用正则表达式根据上面的协议便可对文章进行分段:
private final String imageRegex = "<img>(.*?)</img>";/*** 设置图文混排控件要显示的内容* @param content 要显示的内容*/public void setContent(String content) {// 格式化字符串(替换特殊符号)String text = null;// 设置子View水平居中setGravity(Gravity.CENTER_HORIZONTAL);Pattern pattern = Pattern.compile(imageRegex);Matcher matcher = pattern.matcher(content);while (matcher.find()) {// 加载文字text = content.substring(startPos, matcher.start());if (!TextUtils.isEmpty(text)) {appendTextView(clearNewlineChar(text));}// 加载图片appendImageView(content.substring(matcher.start() + 5, matcher.end() - 6));startPos = matcher.end();}// 加载最后一个图片后面的文字text = content.substring(startPos);if (!TextUtils.isEmpty(text)) {appendTextView(clearNewlineChar(text));}
}
step2: 加载分段后的文字部分
/*** 动态添加文本内容* @param content*/
private void appendTextView(String content) {if (!TextUtils.isEmpty(content)) {TextView textView = new TextView(context);textView.setTextIsSelectable(true);textView.setText(content);textView.setGravity(Gravity.LEFT);textView.getPaint().setTextSize(42);textView.setLineSpacing(0, 1.4f);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);params.bottomMargin = dpToPx(12);params.leftMargin = dpToPx(10);params.rightMargin = dpToPx(10);textView.setLayoutParams(params);addView(textView);}
}
step3: 加载分段后的图片部分
/*** 动态添加图片* @param imageUrl*/
private void appendImageView(String imageUrl) {ImageView imageView = new ImageView(context);final int screenWidth = getDeviceScreenWidth();LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(screenWidth, (int) (screenWidth * 2.0 / 3));params.bottomMargin = dpToPx(12);imageView.setLayoutParams(params);ImageLoader.getInstance().displayImage(imageUrl, imageView);addView(imageView);
}
源码
public class MixedTextImageLayout extends LinearLayout {private int startPos = 0;private Context context;private final String articleRegex = "((<img>(.*?)</img>)|(\\{poi\\}(.*?)\\{/poi\\}))";private final String imageRegex = "<img>(.*?)</img>";public MixedTextImageLayout(Context context) {super(context);this.context = context;setOrientation(VERTICAL);}public MixedTextImageLayout(Context context, AttributeSet attrs) {super(context, attrs);this.context = context;setOrientation(VERTICAL);}public MixedTextImageLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);this.context = context;setOrientation(VERTICAL);}/*** 设置图文混排控件要显示的内容* @param content 要显示的内容*/public void setContent(String content) {// 格式化字符串(替换特殊符号)String text = null;setGravity(Gravity.CENTER_HORIZONTAL);Pattern pattern = Pattern.compile(imageRegex);Matcher matcher = pattern.matcher(clearNeedlessChars(content));while (matcher.find()) {text = content.substring(startPos, matcher.start());if (!TextUtils.isEmpty(text)) {appendTextView(clearNewlineChar(text));}appendImageView(content.substring(matcher.start() + 5, matcher.end() - 6));startPos = matcher.end();}text = content.substring(startPos);if (!TextUtils.isEmpty(text)) {appendTextView(clearNewlineChar(text));}}/*** 动态添加文本内容* @param content*/private void appendTextView(String content) {if (!TextUtils.isEmpty(content)) {TextView textView = new TextView(context);textView.setTextIsSelectable(true);textView.setText(content);textView.setGravity(Gravity.LEFT);textView.getPaint().setTextSize(42);textView.setLineSpacing(0, 1.4f);LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);params.bottomMargin = dpToPx(12);params.leftMargin = dpToPx(10);params.rightMargin = dpToPx(10);textView.setLayoutParams(params);addView(textView);}}/*** 动态添加图片* @param imageUrl*/private void appendImageView(String imageUrl) {ImageView imageView = new ImageView(context);final int screenWidth = getDeviceScreenWidth();LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(screenWidth, (int) (screenWidth * 2.0 / 3));params.bottomMargin = dpToPx(12);imageView.setLayoutParams(params);ImageLoader.getInstance().displayImage(imageUrl, imageView);addView(imageView);}/*** 清除多余的字符* @param str* @return*/private String clearNeedlessChars(String str) {str = str.replaceAll("&","&");str = str.replaceAll(""","\""); //"str = str.replaceAll(" ","\t");// 替换跳格str = str.replaceAll(" "," ");// 替换空格str = str.replaceAll("<","<");str = str.replaceAll(">",">");str = str.replaceAll("\r","");str = str.replaceAll("\n","");str = str.replaceAll("\t","");return str;}/*** 清除多余的尾部换行符 注意:replaceFirst不会替换字符串本身的内容* @param content* @return*/private String clearNewlineChar(String content) {int startPos = 0;int endPos = content.length() - 1;// 清除文字首部多余的换行符while (startPos <= endPos) {if (content.charAt(startPos) == '\n' || content.charAt(startPos) == '\r') {startPos++;// 当所有内容都是换行符的情况if (startPos > endPos) {content = "";endPos -= startPos;break;}} else {// 获取清除后的字符串,并重新设置尾部位置content = content.substring(startPos);endPos -= startPos;break;}}// 清除文字尾部多余的换行符while (endPos > 0) {if (content.charAt(endPos) == '\n' || content.charAt(endPos) == '\r') {endPos--;} else {content = content.substring(0, endPos+1);break;}}return content;}/*** 获取屏幕宽度* @return*/public int getDeviceScreenWidth() {DisplayMetrics dm = getResources().getDisplayMetrics();int w = dm.widthPixels;int h = dm.heightPixels;return w > h ? h : w;}/*** dp转px* @param dp* @return*/public int dpToPx(int dp) {return (int) (getResources().getDisplayMetrics().density * ((float) dp)+0.5);}
}
使用
在布局文件中定义之后,代码中直接调用setContent()方法设置内容即可。
mixedLayout = (MixedTextImageLayout) findViewById(R.id.mixed_layout);mixedLayout.setContent(content);
效果
总结
其实图文混排有多种方式可以实现,最常用的可能就是直接用WebView加载了,简单易用且样式丰富,但是对移动端而言,交互相对较难。所以具体使用哪种方式,还是要根据需求进行取舍。当然,这种方式除了加载文字和图片之外,也可以加载其他布局(需要对代码进行扩展)。
打造原生的图文混排控件相关推荐
- 可自由配置的图文混排控件——组合法
1.我们希望控件可以这样定制: <com.itemp.imagetext.ImageText android:layout_width="wrap_content" andr ...
- android多媒体图文混排,android图文混排
背景 最近我们的产品来了个新的模块,给学生做题提高成绩的.需求如下: 支持单选.多选.填空题 支持图片文字混排 输入框有交互,排版精致美观 为了体验优化,不能使用网页实现效果 思路分析 我们的图文混排 ...
- Android使用HtmlTextView控件实现新闻详情图文混排
在实现新闻详情的时候,安卓也有类似富文本的控件,但是使用webview或者textview等方法,每种方法各有优劣,不是很完美.今天给大家介绍一个安卓控件--HtmlTextView,实现详情页图文混 ...
- Android动态图文混排,Android控件TextView实现静态图与动态GIF图文混排
最近做项目功能时,需要在TextView中展示图文,刚开始做的时候以为很简单,只需要用个ImageView跟TextView来展示就行了,可是发现这样做,不能实现我们需要的效果,这就需要涉及到富文本T ...
- Android控件TextView实现静态图与动态GIF图文混排
最近做项目功能时,需要在TextView中展示图文,刚开始做的时候以为很简单,只需要用个ImageView跟TextView来展示就行了,可是发现这样做,不能实现我们需要的效果,这就需要涉及到富文本T ...
- 使用CoreText实现图文混排
2019独角兽企业重金招聘Python工程师标准>>> OS没有现成的支持图文混排的控件,而要用多个基础控件组合拼成图文混排这样复杂的排版,是件很苦逼的事情.对此的解决方案有使用Co ...
- android 点击图片事件,android图文混排点击事件
图文混排顾名思义就是把文字和图片混合排列在一起,比较简单的需求我们也可以通过TextView和ImageView配合使用来达到目的,但是遇到稍微复杂一些的情况这种方法就不适用了. 做这样一个按钮: 对 ...
- 仿微信表情输入键盘(支持 Gif 表情图文混排 )
作者 | PandaQ404 地址 | http://www.jianshu.com/p/fddca2b0a26b 声明 | 本文是 PandaQ404 原创,已获授权发布,未经原作者允许请勿转载 简 ...
- mysql emoy表情_GitHub - PandaQAQ/PandaEmoView: emoji gif 表情图文混排,仿微信表情输入...
该库具有以下特点: 支持 emoji 表情图片 支持 gif 动态表情输入显示 支持单张贴图表情(与微信收藏表情一致) 支持题图表情库的添加删除 效果图: 快速使用 引入库 compile 'com. ...
最新文章
- python 自定义模块的发布和安装
- Python import以及os模块
- 转载:tensorflow保存训练后的模型
- jqery 实现滚动图片【三】
- 建筑电气工程设计常用图形和文字符号_想要识图无忧?电气工程图图形符号全能图解,电工最爱识图助手...
- memcache入门
- 监护仪系统都是Linux吗,基于Linux和MiniGUI的心电监护仪设计 (1)
- dcmtk在PACS开发中的应用(基础篇) 作者:冷家锋 第四章 工作列表(Work List)(二)...
- 易筋SpringBoot 2.1 | 第廿二篇:SpringBoot的Mybatis分页插件PageHelper
- 记录开发过程中第一次遇到的回调地狱
- 微软原版Windows 8 原版镜像
- 静态文件html中加入php的Url,YII中URL伪静态加前缀.html的方法
- eclipse SVN插件的缓存清理
- 一周技术学习笔记(第58期)-如何突破第四章障碍
- R语言基础 期中考试
- Windows Server 2008之旅??Windows Server Backup功能_闲云野鹤?精神家园_百度空间
- Word的样式库在 选项卡中_如何使用word文档?word文档使用技巧教程?
- vue实现鼠标移入移出事件
- 修改服务器hba卡pciid,HBA卡更换步骤.doc
- trac linux,CentOS下安装Trac笔记
热门文章
- 微积分 重点难点记录
- 雷电模拟器adb devices返回127.0.0.1:5555 offline分析和解决办法
- 代码diff服务改进方案
- java Date.getDay()
- Swagger接口测试工具。
- npm ERR! gyp verb check python checking for Python executable “python2“ in the PATH
- 108页《SpringBoot 学习笔记完整教程》PDF附下载
- 全选与反选 (转)
- 实验七 计数器及其应用
- 使用jstack查看线程