随着互联网的发展,信息展示的元素越来越丰富,无论是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("&amp;","&");str = str.replaceAll("&quot;","\"");  //"str = str.replaceAll("&nbsp;&nbsp;","\t");// 替换跳格str = str.replaceAll("&nbsp;"," ");// 替换空格str = str.replaceAll("&lt;","<");str = str.replaceAll("&gt;",">");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. 可自由配置的图文混排控件——组合法

    1.我们希望控件可以这样定制: <com.itemp.imagetext.ImageText android:layout_width="wrap_content" andr ...

  2. android多媒体图文混排,android图文混排

    背景 最近我们的产品来了个新的模块,给学生做题提高成绩的.需求如下: 支持单选.多选.填空题 支持图片文字混排 输入框有交互,排版精致美观 为了体验优化,不能使用网页实现效果 思路分析 我们的图文混排 ...

  3. Android使用HtmlTextView控件实现新闻详情图文混排

    在实现新闻详情的时候,安卓也有类似富文本的控件,但是使用webview或者textview等方法,每种方法各有优劣,不是很完美.今天给大家介绍一个安卓控件--HtmlTextView,实现详情页图文混 ...

  4. Android动态图文混排,Android控件TextView实现静态图与动态GIF图文混排

    最近做项目功能时,需要在TextView中展示图文,刚开始做的时候以为很简单,只需要用个ImageView跟TextView来展示就行了,可是发现这样做,不能实现我们需要的效果,这就需要涉及到富文本T ...

  5. Android控件TextView实现静态图与动态GIF图文混排

    最近做项目功能时,需要在TextView中展示图文,刚开始做的时候以为很简单,只需要用个ImageView跟TextView来展示就行了,可是发现这样做,不能实现我们需要的效果,这就需要涉及到富文本T ...

  6. 使用CoreText实现图文混排

    2019独角兽企业重金招聘Python工程师标准>>> OS没有现成的支持图文混排的控件,而要用多个基础控件组合拼成图文混排这样复杂的排版,是件很苦逼的事情.对此的解决方案有使用Co ...

  7. android 点击图片事件,android图文混排点击事件

    图文混排顾名思义就是把文字和图片混合排列在一起,比较简单的需求我们也可以通过TextView和ImageView配合使用来达到目的,但是遇到稍微复杂一些的情况这种方法就不适用了. 做这样一个按钮: 对 ...

  8. 仿微信表情输入键盘(支持 Gif 表情图文混排 )

    作者 | PandaQ404 地址 | http://www.jianshu.com/p/fddca2b0a26b 声明 | 本文是 PandaQ404 原创,已获授权发布,未经原作者允许请勿转载 简 ...

  9. mysql emoy表情_GitHub - PandaQAQ/PandaEmoView: emoji gif 表情图文混排,仿微信表情输入...

    该库具有以下特点: 支持 emoji 表情图片 支持 gif 动态表情输入显示 支持单张贴图表情(与微信收藏表情一致) 支持题图表情库的添加删除 效果图: 快速使用 引入库 compile 'com. ...

最新文章

  1. python 自定义模块的发布和安装
  2. Python import以及os模块
  3. 转载:tensorflow保存训练后的模型
  4. jqery 实现滚动图片【三】
  5. 建筑电气工程设计常用图形和文字符号_想要识图无忧?电气工程图图形符号全能图解,电工最爱识图助手...
  6. memcache入门
  7. 监护仪系统都是Linux吗,基于Linux和MiniGUI的心电监护仪设计 (1)
  8. dcmtk在PACS开发中的应用(基础篇) 作者:冷家锋 第四章 工作列表(Work List)(二)...
  9. 易筋SpringBoot 2.1 | 第廿二篇:SpringBoot的Mybatis分页插件PageHelper
  10. 记录开发过程中第一次遇到的回调地狱
  11. 微软原版Windows 8 原版镜像
  12. 静态文件html中加入php的Url,YII中URL伪静态加前缀.html的方法
  13. eclipse SVN插件的缓存清理
  14. 一周技术学习笔记(第58期)-如何突破第四章障碍
  15. R语言基础 期中考试
  16. Windows Server 2008之旅??Windows Server Backup功能_闲云野鹤?精神家园_百度空间
  17. Word的样式库在 选项卡中_如何使用word文档?word文档使用技巧教程?
  18. vue实现鼠标移入移出事件
  19. 修改服务器hba卡pciid,HBA卡更换步骤.doc
  20. trac linux,CentOS下安装Trac笔记

热门文章

  1. 微积分 重点难点记录
  2. 雷电模拟器adb devices返回127.0.0.1:5555 offline分析和解决办法
  3. 代码diff服务改进方案
  4. java Date.getDay()
  5. Swagger接口测试工具。
  6. npm ERR! gyp verb check python checking for Python executable “python2“ in the PATH
  7. 108页《SpringBoot 学习笔记完整教程》PDF附下载
  8. 全选与反选 (转)
  9. 实验七 计数器及其应用
  10. 使用jstack查看线程