XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/tv_indent"android:layout_width="wrap_content"android:layout_height="wrap_content" />
</LinearLayout>

代码:

  • autoSplitText(tv,indent):该方法用来切割字符串,在需要换行的文本处添加换行符和缩进空格。
    private String autoSplitText(final TextView tv, final String indent) {//此处拿到得还是一串长文本final String rawText = tv.getText().toString(); //原始文本final Paint tvPaint = tv.getPaint(); //paint,包含字体等信息final float tvWidth = tv.getWidth() - tv.getPaddingLeft() - tv.getPaddingRight(); //控件本身宽度//将缩进转换成空格String indentSpace = "";float indentWidth = 0;if (!TextUtils.isEmpty(indent)) {float rawIndentWidth = tvPaint.measureText(indent); //获取缩进的宽度if (rawIndentWidth < tvWidth) { //如果缩进宽度比控件本身宽度小的话while ((indentWidth = tvPaint.measureText(indentSpace)) < rawIndentWidth) {//将缩进的宽度转变为空格的形式表示出来indentSpace += " ";}//减去一个空格宽度indentSpace = indentSpace.substring(0, indentSpace.length() - 1);}}//将原始文本按行拆分// \r 光标重新回到本行开头// \n 光标往下一行String[] rawTextLines = rawText.replaceAll("\r", "").split("\n");StringBuilder sbNewText = new StringBuilder();for (String rawTextLine : rawTextLines) {if (tvPaint.measureText(rawTextLine) <= tvWidth) {//如果整行宽度在控件可用宽度之内,就不处理了sbNewText.append(rawTextLine);} else {//如果整行宽度超过控件可用宽度,则按字符测量,在超过可用宽度的前一个字符处手动换行float lineWidth = 0;//记录文字行宽for (int cnt = 0; cnt != rawTextLine.length(); ++cnt) {char ch = rawTextLine.charAt(cnt);if (lineWidth < 0.1f && cnt != 0) {//当lineWidth宽度等与0并且cnt不等于0时候,可以确认是在第二行,此时在行头加上缩进。sbNewText.append(indentSpace);lineWidth += indentWidth;}lineWidth += tvPaint.measureText(String.valueOf(ch));if (lineWidth <= tvWidth) {//文字行宽小于控件行宽,将文字添加进StringBuilder中。sbNewText.append(ch);} else {//如果文字行宽大于控件行宽,加入换行符号。清空文字宽度,cnt 减 1后再重新计算。//走到这一步之后会从for循环开头走,在下一行加缩进。sbNewText.append("\n");lineWidth = 0;--cnt;}}}sbNewText.append("\n");}//把结尾多余的\n去掉if (!rawText.endsWith("\n")) {sbNewText.deleteCharAt(sbNewText.length() - 1);}return sbNewText.toString();}
}
  • 使用

    • 注册一个观察者来监听视图,当视图树的布局发生改变或者View在视图树的可见状态发生改变时会调用的接口ViewTreeObserver.OnGlobalLayoutListener()。
    • 并且在ViewTreeObserver.OnGlobalLayoutListener()回调函数中设置SpannableStringBuilder点击也不会有冲突。
final TextView tvIndent = (TextView) findViewById(R.id.tv_indent);
String upgradeContent = "1,Google LLC 是一家美国跨国科技公司,专门从事互联网相关服务和产品,包括在线广告技术,搜索引擎,云计算,软件和硬件。\n2,Google由Larry Page和Sergey Brin于1998年创立,当时他们是博士。学生在斯坦福大学在加州。\n3,他们共同拥有约14%的股份,并通过超级投票控制56%的股东投票权股票。\n4,他们于1998年9月4日将Google合并为一家私营公司。\n5,2004年8月19日首次公开募股(IPO),谷歌搬到位于加利福尼亚州山景城的总部,绰号为Googleplex。\n6,2015年8月,谷歌宣布计划重组其作为一家名为Alphabet Inc.的企业集团的各种利益。谷歌是Alphabet的主要子公司,并将继续成为Alphabet互联网利益的保护伞公司。\n7,Sundar Pichai被任命为Google首席执行官,取代Larry Page成为Alphabet的首席执行官。";
tvIndent.setText(upgradeContent);
tvIndent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)@Overridepublic void onGlobalLayout() {//回调之后取消监听,防止回调被来回调取。tvIndent.getViewTreeObserver().removeOnGlobalLayoutListener(this);String indentTextDesc = autoSplitText(tvIndent, "1,");String targetClick = "搜索引擎";SpannableStringBuilder contentSpannableBuilder = new SpannableStringBuilder(indentTextDesc);contentSpannableBuilder.setSpan(new ClickableSpan() {@Overridepublic void onClick(View widget) {Toast.makeText(MainActivity.this, "Toast 被点击", Toast.LENGTH_LONG).show();}@Overridepublic void updateDrawState(TextPaint ds) {ds.setUnderlineText(true);ds.setColor(Color.parseColor("#067ce4"));ds.setFakeBoldText(true);}}, indentTextDesc.indexOf(targetClick), indentTextDesc.indexOf(targetClick) + targetClick.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);tvIndent.setMovementMethod(LinkMovementMethod.getInstance());tvIndent.setText(contentSpannableBuilder);}
});

效果:

TextView 悬挂缩进实现及解析相关推荐

  1. Android Textview缩进之悬挂缩进

    很多地方都需要用到类似这样的悬挂缩进,排版看起来比较整齐.代码实现起来也很简单,几行就搞定了. String str = "1. Because of the protocol implem ...

  2. Endnote X9.1 参考文献悬挂缩进

    Endnote X9.1 参考文献悬挂缩进 原来参考文献:(style) 修改后参考文献:(style) 具体操作方法(Method): 在word中插入一篇引文:打开EndnoteX9.1软件,选中 ...

  3. CSS实现首行缩进和悬挂缩进

    首行缩进 text-indent控制首行缩进,后加缩进长度,数值可正可负,单位可以是em,百分比,或者绝对单位.以数值2为例,取值可以是: 1. 2em 参见em,相对长度单位,为父元素文本字体尺寸的 ...

  4. Latex---局部调大字体--下划线--首行缩进--悬挂缩进

    1 调整字体大小 \tiny \scriptsize \footnotesize \small \normalsize \large \Large \LARGE \huge \Huge 2 下划线 \ ...

  5. css div 悬挂缩进_CSS中的经典字体效果:悬挂缩进

    css div 悬挂缩进 A hanging indent, or hanging paragraph, is a paragraph in which the opening line is lef ...

  6. 如何在Microsoft PowerPoint中创建或删除悬挂缩进

    A hanging indent (often called a negative indent) positions the first line of a paragraph a predeter ...

  7. 调整字符宽度后,首行缩进或悬挂缩进的排版“乱了”

    调整字符宽度后,可能会出现段落首行缩进和悬挂缩进的排版 "乱了"的现象.本文针对该现象的出现原因进行分析,并整理了解决办法. 1. 现象 (1)未调整字符宽度时,对段落中文本设置悬 ...

  8. EndNote文献悬挂缩进的设置方法及设置参考文献序号后面空格长度

    一.EndNote文献悬挂缩进的设置方法 写论文时使用EndNote来插入和管理参考文献是一种非常方便的方法,但有时不同的杂志要求插入的文献要求第二行缩进格式,或者不缩进. 1.在EndNote中Ed ...

  9. 20210712 专利自动编号,悬挂缩进

    把悬挂缩进改下就OK

  10. 首行缩进和悬挂缩进的区别

    首行缩进和悬挂缩进是常见的段落缩进方式,用于调整段落的排版样式.它们可以在文本处理软件中应用于段落或选定的文本部分. 首行缩进:首行缩进是指将段落的第一行向内缩进一定的距离,以使段落的其余行保持靠近页 ...

最新文章

  1. CoreSight介绍篇
  2. 风格迁移应用_[风格迁移][超分][ECCV2016]Perceptual Losses for Real...
  3. git 改了一段代码不想要了_初识Git
  4. 挑选SaaS企业需要注意十要素
  5. 【10.20校内测试】【小模拟】【无向图建树判奇偶环】【树上差分】
  6. C# 获取对象 大小 Marshal.SizeOf (sizeof 只能在不安全的上下文中使用)
  7. 团队作业8—团队项目用户验收评审
  8. Git学习文档之一 学习文档-合并分支
  9. Linux下C语言的调试器 Gdb
  10. php excel数据导出
  11. 大学物理复盘 | 简明大学物理学第一章——质点运动学思维导图梳理(复习专用)
  12. 如何备份linux磁盘空间,请问怎么备份整个硬盘又快又省空间?
  13. 数电Day06:主从触发器和边沿触发器,触发器的逻辑符号,时序波形
  14. matlab中imshow函数输出图像全白全黑问题
  15. js版的倒计时(月-日-时-分-秒-毫秒)
  16. 【Web前端初学笔记】②HTML基本结构标签,VSCode工具创建页面,网页开发工具
  17. PARI/GP 语言:从入门到实现大素数判定与大数分解
  18. web网站访问计数器
  19. 数字2019的分解问题
  20. 洛谷 P1309 瑞士轮 归并

热门文章

  1. 深圳海伊视讯布控球成功对接海康萤石云平台安装调式
  2. Linux 管道 管道命令 命名管道
  3. android极光推送sequence,极光推送接入
  4. 【数据库】数据、数据库、数据库管理系统、数据库系统
  5. The LINQ expression node type 'ArrayIndex' is not supported in LINQ to Entities.
  6. java关于文件上传和下载,保存到后台并修改名字。
  7. Lab4 Architecture Lab
  8. 自然数e的故事(转)
  9. android 仿ios数字密码解锁界面
  10. 那些堪比照片质感的PhotoRealistic Style Transfer系列