Android TextView一些常用概念解析

  • 现代 Android 中的 leading

    • 通常为0 ,因为行间距由 lineSpacingMultiplierlineSpacingExtra 属性管理。
    • 不再依赖于 Paint.FontMetrics 中的 leading 来调整行间距。
  • 行间距管理

    • 优先使用 lineSpacingMultiplierlineSpacingExtra 来调整行间距。
    • 结合两者使用 可以实现灵活且精确的行间距控制。
    • 高级控制 :通过自定义 LineHeightSpan 或其他高级方法,可以实现更细粒度的行高管理。
  • 设计和可读性

    • 适当的行间距 提高文本的可读性和整体界面的美观性。
    • 根据字体和文本大小 调整行间距,确保在各种设备和配置下的最佳显示效果。

通过理解现代 Android 中行间距的管理方式,以及合理应用相关属性,您可以在 TextView 中实现理想的文本布局,提升用户的阅读体验和界面美感。

js 复制代码
+--------------------------+
|          Top             |
|                          |
|  Ascent                  |
|    _________             |
|   |         |            |
|   |  Text   |            |  <-- Baseline of Line 1
|   |         |            |
|   |_________|            |
|     Descent              |
|                          |
|      Leading Space       |  <-- Space between Baselines
|                          |
|    _________             |
|   |         |            |
|   |  Text   |            |  <-- Baseline of Line 2
|   |         |            |
|   |_________|            |
|     Descent              |
|                          |
|         Bottom           |
+--------------------------+
  • baseline:水平方向的一条线,字符通常以此为参考对齐,绝大多数字符"脚"都在这条线上。

  • ascent:从 baseline 往上到字符最高处的距离(多为负值)。

  • descent:从 baseline 往下到字符最低处的距离(通常为正值)。

  • top :字符最顶端可能达到的距离(通常比 ascent 更"高"一点,负值更大)。

  • bottom :字符最底端可能达到的距离(通常比 descent 更"低"一点,正值更大)。

在 Android 中,如果要获取单行文本的上述度量,可以通过 TextViewPaint 对象或直接使用 Paint 本身:

js 复制代码
TextView textView = findViewById(R.id.your_text_view);

// 1. 获取 Paint 对象
Paint paint = textView.getPaint();

// 2. 获取 FontMetrics
Paint.FontMetrics fontMetrics = paint.getFontMetrics();

// 3. 取出 top, ascent, descent, bottom, baseline(baseline 通常以 0 参考值呈现)
float topValue = fontMetrics.top;
float ascentValue = fontMetrics.ascent;
float descentValue = fontMetrics.descent;
float bottomValue = fontMetrics.bottom;
float leadingValue = fontMetrics.leading;  // leading 在现代安卓中经常为0

行间距的计算

TextView 中,行间距(行高)的计算主要基于以下几个因素:

  1. 字体的 ascentdescent
  2. 行间距属性 lineSpacingExtralineSpacingMultiplier

计算公式如下:

js 复制代码
行高 = ( |ascent| + descent ) * lineSpacingMultiplier + lineSpacingExtra
  • 获取纯文本的显示区域坐标
js 复制代码
paint.getTextBounds("afyq", 0, "abab".length, bounds)

bounds返回的就是左上右下,如果你想实现文字完全贴边,可以考虑这种方式,下图中的af完全贴近屏幕了。

  • 如何让文本完全居中: 在代码中,如果我们只设置宽高的二分之一,这只是代表了文本的基线是居中的,文字整体显示其实并不居中,要想让整个都居中,我们需要对基线做偏移,因为文本的绘制都是以基线为基准进行的:
js 复制代码
canvas.drawText("afyq", width / 2f, height / 2f, paint)

将上边的代码修改为:

js 复制代码
canvas.drawText("afyq", width / 2f, height / 2f - (fontMetrics.ascent + fontMetrics.descent) / 2f, paint)

对于同一种字体,它的ascent和descent是固定的,因此通过对基线做上边的偏移,就可以实现完全居中了,需要注意ascent是负值,而descent是正值,因此上边的height / 2f 减去的是一个负数,因此才能保证基线是向下偏移的。

上边就是偏移基线之后一个完全居中的文本。不做偏移,看到的就是这个效果:

两者对比情况显而易见了。

相关推荐
mldong4 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排5 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60615 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角6 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!7 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰7 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi8 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen9 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马10 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒10 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端