harmony 鸿蒙文本测量(ArkTS)

  • 2025-06-12
  • 浏览 (5)

文本测量(ArkTS)

场景介绍

文本测量指的是在图形绘制中,对文本的尺寸和布局进行评估,计算文本在给定字体和样式下占用的空间(例如宽度、高度和其他相关信息)的过程。文本测量用于文本排版、布局、渲染以及调整文本显示的位置和大小等场景,便于对界面的布局和呈现更好地把控和调整,以达到设计预期。

当前主要支持以下方面的文本测量能力:

  • 文本宽度:测量给定文本在特定字体、大小和样式下的水平长度。

  • 文本高度:测量给定文本的垂直高度,通常涉及文本的上升线、下降线等。

  • 行间距:测量多行文本之间的垂直距离,通常与文本的行距相关。

  • 字符间距:测量单个字符之间的水平距离,通常与字形和字体设计有关。

接口说明

文本测量中常用接口如下表所示,详细接口说明参考@ohos.graphics.text (文本模块)

接口名 描述
getLongestLine(): number 获取当前段落最长行的宽度,建议实际使用时将返回值向上取整。
getLongestLineWithIndent(): number 获取当前段落最长行的宽度(该宽度包含当前行缩进的宽度),建议实际使用时将返回值向上取整。
getTextLines(): Array<TextLine> 获取当前段落文本行对象数组。
getLineMetrics(): Array<LineMetrics> 获取段落所有行的度量信息。包含行的高度、宽度、起始坐标等信息。
getLineMetrics(lineNumber: number): LineMetrics |undefined 获取段落指定行的度量信息。包含行的高度、宽度、起始坐标等信息。超出当前段落排版后最大行数后返回 undefined

开发步骤

  1. 导入依赖的相关模块。
   import { text } from '@kit.ArkGraphics2D';
  1. 创建段落样式,并使用构造段落生成器PargraphBuilder生成段落实例。
   // 设置文本样式
   let myTextStyle: text.TextStyle = {
       color: { alpha: 255, red: 255, green: 0, blue: 0 },
       fontSize: 100
   };
   // 创建一个段落样式对象,以设置排版风格
   let myParagraphStyle: text.ParagraphStyle = {
       textStyle: myTextStyle,
       wordBreak:text.WordBreak.NORMAL
   }
   // 创建一个段落生成器
   let paragraphBuilder: text.ParagraphBuilder = new text.ParagraphBuilder(myParagraphStyle, new text.FontCollection());
  1. 设置文本样式,添加文本内容,并生成段落文本用于后续文本的绘制显示。
   // 在段落生成器中设置文本样式
   paragraphBuilder.pushStyle(myTextStyle);
   // 在段落生成器中设置文本内容
   paragraphBuilder.addText("文本测量测试");
   // 通过段落生成器生成段落
   let paragraph = paragraphBuilder.build();
  1. 调用测量相关接口,获取指定的测量信息。
   // case1: 获取排版后最长行行宽
   let longestLineWidth = paragraph.getLongestLine();
   // case2: 获取排版后最长行行宽(包含缩进)
   let longestLineWithIndentWidth = paragraph.getLongestLineWithIndent()
   // case3: 获取排版后所有行对象
   let textLines = paragraph.getTextLines();
   // case4: 获取排版后指定行对应的度量信息
   let lineCnt = paragraph.getLineCount();
   for (let index = 0; index < lineCnt; index++) {
       let lineMetrics = paragraph.getLineMetrics(index);
   }
   // case5: 获取排版后所有行度量信息数组
   let allLineMetrics = paragraph.getLineMetrics();

完整示例

完整的文本测量示例如下。

// Index.ets
import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI';
import { UIContext } from '@kit.ArkUI';
import { text } from '@kit.ArkGraphics2D';

// 创建一个自定义的渲染节点类,用于绘制文本
class MyRenderNode extends RenderNode {
  async draw(context: DrawContext) {
    // 获取画布canvas对象
    const canvas = context.canvas;
    // 配置文本样式(红色,字号100px)
    let myTextStyle: text.TextStyle = {
      color: {
        alpha: 255,
        red: 255,
        green: 0,
        blue: 0
      },
      fontSize: 100
    };
    // 创建一个段落样式对象,以设置排版风格
    let myParagraphStyle: text.ParagraphStyle = {
      textStyle: myTextStyle,
      wordBreak: text.WordBreak.NORMAL
    };
    // 创建一个段落生成器
    let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, new text.FontCollection());
    // 在段落生成器中设置文本样式
    paragraphBuilder.pushStyle(myTextStyle);
    // 在段落生成器中设置文本内容
    paragraphBuilder.addText("文本测量测试");
    // 通过段落生成器生成段落
    let paragraph = paragraphBuilder.build();
    // 布局
    paragraph.layoutSync(1000);
    // case1: 获取排版后最长行行宽
    let longestLineWidth = paragraph.getLongestLine();
    console.info("longestLineWidth = " + longestLineWidth);

    // case2: 获取排版后最长行行宽(包含缩进)
    let longestLineWithIndentWidth = paragraph.getLongestLineWithIndent();
    console.info("longestLineWithIndentWidth = " + longestLineWithIndentWidth);

    // case3: 获取排版后所有行对象
    let textLines = paragraph.getTextLines();
    for (let index = 0; index < textLines.length; index++) {
      const textline = textLines[index];
      let curLineRange = textline.getTextRange();
      let curLineGlyCnt = textline.getGlyphCount();
      console.info("MetricsMSG: 第" + (index + 1) + "行 TextRange start: " + curLineRange.start + " TextRange end: " + curLineRange.end);
      console.info("MetricsMSG: 第" + (index + 1) + "行字形数量为: " + curLineGlyCnt);
    }

    // case4: 获取排版后指定行对应的度量信息
    let lineCnt = paragraph.getLineCount();
    for (let index = 0; index < lineCnt; index++) {
      let lineMetrics = paragraph.getLineMetrics(index);
      if (lineMetrics) {
        console.info("MetricsMSG: 第" + (index + 1) + "行 lineMetrics width: " + lineMetrics.width);
        console.info("MetricsMSG: 第" + (index + 1) + "行 lineMetrics start index: " + lineMetrics.startIndex + ", end index: " +
        lineMetrics.endIndex);
      }
    }

    // case5: 获取排版后所有行度量信息数组
    let allLineMetrics = paragraph.getLineMetrics();
    console.info("MetricsMSG: 第1行 lineMetrics width: " + allLineMetrics[0].width);
    paragraph.paint(canvas, 0, 800);
  }
}

// 创建文本渲染节点实例
const textNode = new MyRenderNode();
// 定义newNode的大小和位置
textNode.frame = { x: 0, y: 0, width: 400, height: 600 };

class MyNodeController extends NodeController {
  private rootNode: FrameNode|null = null;

  makeNode(uiContext: UIContext): FrameNode {
    this.rootNode = new FrameNode(uiContext);
    if (this.rootNode == null) {
      return this.rootNode;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.frame = {
        x: 0,
        y: 0,
        width: 300,
        height: 50
      };
      renderNode.pivot = { x: 0, y: 0 };
    }
    return this.rootNode;
  }

  addNode(node: RenderNode): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.appendChild(node);
    }
  }

  clearNodes(): void {
    if (this.rootNode == null) {
      return;
    }
    const renderNode = this.rootNode.getRenderNode();
    if (renderNode != null) {
      renderNode.clearChildren();
    }
  }
}

@Entry
@Component
struct RenderTest {
  private myNodeController: MyNodeController = new MyNodeController();

  build() {
    Column() {
      Row() {
        NodeContainer(this.myNodeController)
          .height('100%')
          .position({ x: 30, y: 25 })
      }

        Row() {
          Button("Draw Text")
            .fontSize('16fp')
            .fontWeight(500)
            .margin({ bottom: 24, right: 12 })
            .onClick(() => {
              this.myNodeController.clearNodes();
              this.myNodeController.addNode(textNode);
            })
            .width('50%')
            .height(40)
        }
        .width('100%')
        .justifyContent(FlexAlign.Center) // 设置当前Row容器内子元素在主轴上居中对齐
        .alignItems(VerticalAlign.Bottom) // 设置当前Row容器内子元素在交叉轴(垂直方向)上的对齐方式为底部对齐
        .layoutWeight(1) // 设置当前Row在父容器Column中的布局权重为1
      }
    }
  }

你可能感兴趣的鸿蒙文章

harmony 鸿蒙ArkGraphics 2D(方舟2D图形服务)

harmony 鸿蒙ArkGraphics 2D简介

harmony 鸿蒙基础绘制效果(ArkTS)

harmony 鸿蒙基础绘制效果(C/C++)

harmony 鸿蒙画布的获取与绘制结果的显示(ArkTS)

harmony 鸿蒙画布的获取与绘制结果的显示(C/C++)

harmony 鸿蒙画布操作及状态处理(ArkTS)

harmony 鸿蒙画布操作及状态处理(C/C++)

harmony 鸿蒙复杂绘制效果(ArkTS)

harmony 鸿蒙复杂绘制效果(C/C++)

0  赞