Text组件如何给文本添加下划线
================

#### 问题现象

Text组件本身支持decoration属性，设置文本装饰线样式及其颜色。下划线是用于标注重要文字，突出显示重点内容的重要工具，需要更多的灵活配置和更丰富的显示效果。

#### 背景知识

*   Text组件的[decoration](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-text#decoration)属性只能修改线条样式和颜色，无法修改高度和位置。
*   [onAreaChange](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-component-area-change-event#onareachange)是在组件显示的尺寸、位置等发生变化时触发的事件。
*   [shadow](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-image-effect#shadow)：为组件添加阴影效果。
*   [border](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-border#border)：设置组件边框样式。通过链式调用.border()方法，分别配置边框宽度、颜色、样式。
*   [Web组件](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-basic-components-web)：Web组件提供了网页显示能力，根据页面加载数据来源可以分为三种常用场景，包括加载网络页面、加载本地页面、加载HTML格式的富文本数据。

#### 解决方案

*   **方案一**：将Text文字和底部下划线使用Column容器封装成一个组件，在需要的地方应用。
    
    @Entry
    @Component
    struct Index {
      message: string \= 'Hello World!';
      @State textLength: Length \= 0;
      isKey: boolean \= true;
    
      build() {
        Column() {
          Column() {
            Text(this.message)
              .fontSize(14)
              .fontColor(this.isKey ? '#0A59F7' : '#cd202021')
              .padding({ bottom: 5 })
              .onAreaChange((oldValue: Area, newValue: Area) \=\> {
                this.textLength \= newValue.width;
              })
           _ // 自定义选中文本底部导航条\--单直线_
            if (this.isKey) {
              Column().width(this.textLength).height(2).backgroundColor('#0A59F7');
            }
    
           _ // 自定义选中文本底部导航条\--线性渐变_
            if (this.isKey) {
              Text().width(this.textLength).height(2)
                .linearGradient({
                  direction: GradientDirection.Right,
                  colors: \[\['#0A59F7', 0.0\], \[Color.White, 0.9\]\]
                })
                .margin({ top: 10 })
            }
          }
          .width('100%')
        }
      }
    }
    
    效果预览：
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/af/v3/bVbNRzBYSYWFRY-pHZ0xPg/zh-cn_image_0000002658907835.png?HW-CC-KV=V1&HW-CC-Date=20260709T133903Z&HW-CC-Expire=86400&HW-CC-Sign=17BBDAA876779EA34FCE52E820C2AE6A898547C75B0676D990AFCE2AEF9EFABB "点击放大")
    
*   **方案二**：通过Text组件的decoration参数直接设置基础线条样式。
    
    @Entry
    @Component
    struct Scene2 {
      messageBorder: string \= 'overlay中border绘制下划线';
      messageDecoration: string \= 'overlay中decoration绘制下划线';
      messageTwoLine: string \= '绘制2条装饰线';
    
      build() {
        Column({ space: 20 }) {
          Text('上划线')
            .decoration({ type: TextDecorationType.Overline })
    
          Text('中划线')
            .decoration({ type: TextDecorationType.LineThrough })
    
          Text('下划线')
            .decoration({ type: TextDecorationType.Underline })
    
          Text('装饰线颜色跟随fontColor')
            .fontColor(Color.Black)
            .decoration({ type: TextDecorationType.Underline, color: Color.Transparent })
    
          Text('透明装饰线')
            .fontColor(Color.Blue)
            .decoration({ type: TextDecorationType.Underline, color: '#00FFFFFF' })
    
      _    // overlay中decoration绘制下划线，注意y的位置有下划线避让_
          Text(this.messageDecoration)
            .overlay(this.OverlayNodeDecoration(), {
              align: Alignment.Start,
              offset: { x: 0, y: 0 }
            })
    
        _  // overlay中border绘制下划线，注意y的位置没有下划线避让_
          Text(this.messageBorder)
            .overlay(this.OverlayNodeBorder(), {
              align: Alignment.Start,
              offset: { x: 0, y: -2 }
            })
    
          Text(this.messageTwoLine)
            .decoration({ type: TextDecorationType.Underline })
            .overlay(this.OverlayNodeTwoLine(), {
              align: Alignment.Start,
              offset: { x: 0, y: -10 }
            })
    
         _ // 字体放大后，下划线避让非常明显_
          Text('下划线避让 gjyqp')
            .fontColor(Color.Blue)
            .fontSize(25)
            .decoration({ type: TextDecorationType.Underline })
    
         _ // border绘制的下划线，位置更靠下_
          Text('border绘制下划线 gjyqp')
            .fontColor(Color.Blue)
            .fontSize(25)
            .borderWidth({ bottom: 1 })
        }
        .padding(20)
      }
    
      @Builder
      OverlayNodeDecoration() {
        Text(this.messageDecoration)
        _  // decoration绘制下划线，下划线避让，会导致y的位置出现一段空白_
          .decoration({
            type: TextDecorationType.Underline,
            color: Color.Blue,
            style: TextDecorationStyle.SOLID
          })
          .fontColor(Color.Transparent)
          .hitTestBehavior(HitTestMode.Transparent) _//_ _配置浮层不阻塞交互_
      }
    
      @Builder
      OverlayNodeBorder() {
        Text(this.messageBorder)
          .borderWidth({ bottom: 1 })
          .borderColor(Color.Blue)
          .fontColor(Color.Transparent)
          .hitTestBehavior(HitTestMode.Transparent) _//_ _配置浮层不阻塞交互_
      }
    
      @Builder
      OverlayNodeTwoLine() {
        Text(this.messageTwoLine)
          .borderWidth({ bottom: 1 })
          .borderColor(Color.Blue)
          .fontColor(Color.Transparent)
          .hitTestBehavior(HitTestMode.Transparent) _//_ _配置浮层不阻塞交互_
      }
    }
    
    效果预览：
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/6f/v3/eF07obbQRISKoJHpdJNOKw/zh-cn_image_0000002658787897.png?HW-CC-KV=V1&HW-CC-Date=20260709T133903Z&HW-CC-Expire=86400&HW-CC-Sign=AEF0692847C6B26F7DCF7078357AB56BB5BF43F48256E9B4DA13F809EA939659 "点击放大")
    
*   **方案三**：通过border属性给Text组件添加下边框来实现文字下划线的效果。
    
    @Entry
    @Component
    struct Scene3 {
      build() {
        Column() {
          Text('测试文字')
            .fontSize(15)
            .border({
              width: {
                left: 0,
                right: 0,
                top: 0,
                bottom: 2
              },
              color: { bottom: Color.Gray },
              style: {
                bottom: BorderStyle.Solid _// 线条样式（实线）_
              }
            })
        }
        .width('100%')
      }
    }
    
*   **方案四**：给组件添加阴影效果，通过shadow()方法设置参数,设置垂直方向偏移量（使阴影位于组件下方），最后限制容器高度，强制触发布局约束，实现文字下划线的效果。
    
    @Entry
    @Component
    struct Scene4 {
      build() {
        Column() {
          Text('测试文字')
            .fontSize(15)
            .shadow({
              radius: 5,
              color: Color.Green,
              offsetX: 0,
              offsetY: 50,
              fill: true
            })
            .height(1)
        }
        .width('100%')
      }
    }
    
*   **方案五**：通过Web组件加载本地HTML文件实现特定样式效果。
    
    在rawfile文件夹新建Index.html。
    
    _<!DOCTYPE html>_
    <html>
    <body>
    <p><span class='test-underline'>我是通过Web组件添加的</span></p>
    </body>
    <style>
        .test-underline{
         font-size:50px;
         text-decoration: underline;
         text-decoration-color:black;
         text-decoration-thickness: 0.1em;
       }
    </style>
    </html>
    
    Index.ets。
    
    import web\_webview from '@ohos.web.webview';
    
    @Entry
    @Component
    struct WebComponent {
      controller: web\_webview.WebviewController \= new web\_webview.WebviewController();
    
      build() {
        Column() {
         _ // 通过$rawfile加载本地资源文件。_
          Web({ src: $rawfile('Index.html'), controller: this.controller })
            .fileAccess(true)
            .geolocationAccess(false);
        }
      }
    }
    
    效果预览：
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/57/v3/YLnaeX6lTi6jF7cBUGv0tw/zh-cn_image_0000002628388624.png?HW-CC-KV=V1&HW-CC-Date=20260709T133903Z&HW-CC-Expire=86400&HW-CC-Sign=3BC74555C53EDD924E0CADC604704B72BB9BE0707A5772E1B9DBE6D472EF50AA "点击放大")