# 如何实现文字压在底部下划线上的布局

#### 问题现象

需要实现一个文本底部带有高亮下划线的布局。文字的宽度根据字数动态变化，下划线的宽度比文字宽度多2vp。布局要求文字压在下划线的上方，且仅压住下划线的一半。

问题效果预览：

#### 效果预览

#### 背景知识

*   measureText：计算指定文本在单行布局下的宽度。此方法可以用于动态获取文本的宽度，以便进行精确的布局调整。
*   onAreaChange：获取组件的新旧尺寸和位置信息。此事件回调可以用于在组件尺寸发生变化时进行相应的布局调整。
*   RelativeContainer：相对布局容器，支持容器内部的子元素设置相对位置关系。适用于处理界面复杂的场景，可以对多个子元素进行对齐和排列。

#### 解决方案

**方案一**：

1.  确定下划线宽度。
    *   **方案一**：使用this.getUIContext().getMeasureUtils().measureTextSize()方法获取当前文本的宽度。具体实现如下：
        
        ```
        // 方案一
        textWidthPx: SizeOptions = this.getUIContext().getMeasureUtils().measureTextSize({
          textContent: this.message,
          fontSize: this.TextSize
        });
        
        onPageShow(): void {
          const textWidthVp = this.getUIContext().px2vp(this.textWidthPx.width as number) + 2;
          this.lineWidth = textWidthVp + 'vp';
        }
        ```
        
    *   **方案二**：使用onAreaChange事件回调获取文本宽度。具体实现如下：
        
        ```
        // 方案二
        .onAreaChange((oldValue: Area, newValue: Area) => {
          console.info(`Ace: on area change, oldValue is ${JSON.stringify(oldValue)} value is ${JSON.stringify(newValue)}`);
          this.lineWidth = `${Number(newValue.width) + 2}vp`;
        })
        ```
        
2.  使用px2vp工具函数将获取到的文本宽度由px转换为vp（如果使用onAreaChange获取宽度则不需要单位转换）。
3.  使用RelativeContainer布局将下划线放置当前文本的下方。

完整示例参考如下：

```
@Entry
@Component
struct TextLine {
  message: string = 'HelloWorld';
  TextSize: number = 16;
  @State lineWidth: string = '';

  // 方案一
  textWidthPx: SizeOptions = this.getUIContext().getMeasureUtils().measureTextSize({
    textContent: this.message,
    fontSize: this.TextSize
  });

  onPageShow(): void {
    const textWidthVp = this.getUIContext().px2vp(this.textWidthPx.width as number) + 2;
    this.lineWidth = textWidthVp + 'vp';
  }

  build() {
    RelativeContainer() {
      Text(this.message)
        .id('title')
        .fontSize(this.TextSize)
        .fontWeight(FontWeight.Bold)
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })

          // 方案二
        .onAreaChange((oldValue: Area, newValue: Area) => {
          console.info(`Ace: on area change, oldValue is ${JSON.stringify(oldValue)} value is ${JSON.stringify(newValue)}`);
          this.lineWidth = `${Number(newValue.width) + 2}vp`;
        })

      Column() {
      }
      .width(this.lineWidth)
      .height(12)
      .alignRules({
        center: { anchor: 'title', align: VerticalAlign.Center },
        middle: { anchor: 'title', align: HorizontalAlign.Center }
      })
      .linearGradient({ direction: GradientDirection.Left, colors: [['#a1c4fd', 0], ['#c2e9fb', 1]] })
      .offset({ y: 8 })
      .borderRadius(4)
      .zIndex(-1)
    }
    .height('100%')
    .width('100%')
  }
}
```

**方案二**：

参考官方链接：Text组件如何给文本添加下划线。