博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
FlowTextView源码分析
阅读量:6240 次
发布时间:2019-06-22

本文共 4294 字,大约阅读时间需要 14 分钟。

本文为 项目中 FlowTextView 部分

项目地址:,分析的版本:815bdc3

1.功能介绍

FlowTextView 是对 TextView 的包装,可以在文本中插入图片等其他控件,并且支持 Html 格式文本。

1.1 集成指南

compile 'com.github.deano2390:FlowTextView:2.0.4'

1.2 使用指南

XML文件指定子控件,用法同RelativeLayout布局。

Java代码中指定插入文本

FlowTextView flowTextView = (FlowTextView) findViewById(R.id.ftv);Spanned html = Html.fromHtml("Your html goes here....");flowTextView.setText(html);

2.详细设计

2.1 models包

models包下存放一些抽象概念的模型类。其中域权限均是 public,并不需要通过get/set方法操作。

1.Area

Area 定义一段X轴上区域,表示子控件(即obstacle)占据的区间。

float x1;float x2;float width;

2.Line

Line 代表文本行在x轴上占据的区域。

float leftBound;float rightBound;

3.Obstacle

Obstacle 代表布局中子控件对文本构成的障碍区,由子控件左上和右下点坐标构成。

int topLeftx;int topLefty;int bottomRightx;int bottomRighty;

4.HtmlObject

HtmlObject 代表 html 文本。

String content;int start;int end;float xOffset;    //代表x轴上的实际偏移,非字符偏移TextPaint paint;boolean recycle = false;

5.HtmlLink

HtmlLink 继承 HtmlObject,代表超链接。

float width;float height;float yOffset;    //代表y轴上的实际偏移,非字符偏移String url;

2.2 OnLinkClickListener类

此接口定义了超链接被点击后的回调方法,可以自定义实现.

public void onLinkClick(String url);

2.3 helpers包

一些辅助类

1.PaintHelper

PaintHelper负责存储和管理画笔,避免重复创建画笔类

  • 主要域

ArrayList
mPaintHeap //维持一个画笔集合
  • 主要方法

void recyclePaint(TextPaint paint) //存储画笔TextPaint getPaintFromHeap()       //获取画笔void setColor(int color)

2.SpanParser

SpanParser 负责处理 html 文本。

int mTextLength          //html文本对象长度Spannable mSpannable     //html文本对象PaintHelper mPaintHelper //画笔辅助类FlowTextView mFlowTextView //主控件List
mLinks // html文本中的超链接集合HashMap
sorterMap //html文本集合

主要方法是 parseSpan,负责解析出HtmlObject对象,根据 待解析对象的不同分三种解析方法。

HtmlObject parseSpan(Object span, String content, int start, int end){    if(span instanceof URLSpan)        return getHtmlLink((URLSpan) span, content, start, end, 0);    else if(span instanceof StyleSpan){        return getStyledObject((StyleSpan) span, content, start, end, 0);    else        return getHtmlObject(content, start, end, 0);    }

3.ClickHandler

ClickHandler是OnTouchListener的实现类,主要实现了对超链接点击事件的处理。

SpanParser mSpanParser; //html文本处理类,构造方法传入OnLinkClickListener mOnLinkClickListener; //get/set方法设置double distance         //两点距离float x1,y1,x2,y2       //两点

4.CollisionHelper

calculateLineSpaceForGivenYOffset 方法负责根据组件中的障碍物列表和文本行高度 计算得到使得文本与组件不冲突的 line 对象。

Line calculateLineSpaceForGivenYOffset(        float lineYbottom,         int lineHeight,         float viewWidth,         ArrayList
)

其算法步骤如下:

  1. 建立Line 对象(0~viewWidth),即默认情况下文本行宽度等于组件宽度;

  2. 遍历 obstacles 集合,判断当前 Obstacle 是否与 文本行高度有交叉

  3. 如果有

    • 创建leftArea对象,内循环遍历 obstacles 集合以确定其边界

    • 创建rightArea对象,内循环遍历 obstacles 集合以确定其边界

  4. 在Area集合中寻找范围最大者,最终确定Line对象

这个算法写的极其诡异

2.4 FlowTextView

FlowTextView 继承自 RelativeLayout。

  • 主要域

1.PaintHelper mPaintHelper 2.SpanParser mSpanParser    3.ClickHandler mClickHandler4.int mColor5.int pageHeight        页面高度6.TextPaint mTextPaint  文本画笔  7.TextPaint mLinkPaint  html中超链接文本画笔8.float mTextsize       文本字体大小9.int mTextColor        文本字体颜色10.Typeface typeFace    文本字体类型11.mDesiredHeight       整个控件高度12.boolean needsMeasure 空间是否需要重新测量13.ArrayList
obstacles 布局中已存在的控件障碍列表14.CharSequence mText 显示文本15.boolean mIsHtml 文本是否是 html 格式 16.float mSpacingMult; 17.float mSpacingAdd;18.List
lineObjects19.HtmlObject htmlLine
  • 核心方法

1.setText 方法将导致控件重绘

public void setText(CharSequence text) {    mText = text;    if (text instanceof Spannable) {        mIsHtml = true;        mSpanParser.setSpannable((Spannable) text);    } else {        mIsHtml = false;    }    this.invalidate();}

2.onDraw方法 绘制

扼要分析

//1.初始化所有Obstacle,并获得子组件最大高度int lowestYCoord = findBoxesAndReturnLowestObstacleYCoord();//2.拆分文本并处理String[] blocks = mText.toString().split("\n");for (int block_no = 0; block_no <= blocks.length - 1; block_no++){    String thisBlock = blocks[block_no];    while (thisBlock.length() > 0) {        //3.文本行数+1,并获得绘图起点和文本水平范围        lineIndex++;        yOffset = getPaddingTop() + lineIndex * lineHeight - (getLineHeight() + mTextPaint.getFontMetrics().ascent);        Line thisLine = CollisionHelper.calculateLineSpaceForGivenYOffset(yOffset, lineHeight, mViewWidth, obstacles);        xOffset = thisLine.leftBound;        maxWidth = thisLine.rightBound - thisLine.leftBound;        float actualWidth;        //4.处理 actualWidth 与 maxWidth之间的矛盾    }}

3.总体设计

图片描述

转载地址:http://pgdia.baihongyu.com/

你可能感兴趣的文章
用 Quartz 画聊天对话框背景实例
查看>>
Quartz2D简单绘制之饼状图
查看>>
你优化系统的目标是什么?
查看>>
SVN(64位)报 Failed to load JavaHL Library. 的解决方法
查看>>
基本运算符
查看>>
黄聪:WordPress 多站点建站教程(三):主站如何调用子站的文章内容、SQL语句如何写?...
查看>>
Activity的启动模式 4种launchMode Intent.FLAG_NEW_TASK 详解
查看>>
hdu 2254 奥运 **
查看>>
数据结构基础
查看>>
UltraISO制作ISO镜像文件
查看>>
ASP.NET MVC 之自定义HtmlHelper
查看>>
声明顺序
查看>>
memcpy内存重叠的解决
查看>>
保存和恢复activity的状态数据[转]
查看>>
JS中call、apply的用法说明
查看>>
C#中对于Enum类型的遍历
查看>>
使用tomcat启动dubbo项目
查看>>
crontab + shell脚本实现文件重命名
查看>>
谈谈-ConstraintLayout完全解析
查看>>
fluent-ffmpeg 常用函数
查看>>