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 减去的是一个负数,因此才能保证基线是向下偏移的。

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

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

相关推荐
technology_x7 小时前
2026年财务报表分析软件测评:兼容与安全解析
java·服务器·前端
程序员鱼皮7 小时前
Claude Opus 5 全新发布,7 大项目实测,夯还是拉?半价吊打 Fable 5?
前端·后端·ai编程
极简前端打杂工7 小时前
从0到1搭建通用低代码平台(-)— 表单设计器
前端·全栈
吃饺子不吃馅7 小时前
那就和前端好好道个别吧
前端
_瑞7 小时前
试图教会你用 Xcode Instruments
前端·ios·xcode
海带紫菜菠萝汤8 小时前
WebCodecs API 实战:浏览器原生视频编解码的原理与性能测试
前端·javascript·音视频·视频编解码
一位正在转型AI全栈的前端工程师8 小时前
AI 全栈学习之旅 - Week2:从零搭建一个可部署的 AI 聊天应用
前端
aixingpan8 小时前
aixingpan.cn API开发文档:api_docs_trichart_natal_solararc_transit2接口指南
前端·php
Ayayoyo8 小时前
公平随机转盘的前端实现:Web Crypto API、拒绝采样与加权抽取
前端
程序员黑豆9 小时前
鸿蒙应用开发:@Link 装饰器实现父子组件双向同步
前端·后端·harmonyos