如何通过计算和偏移实现消息气泡的效果
==================

#### 问题现象

如何通过组件的搭配使用，实现类似如下消息气泡效果：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/2e/v3/uII-_2jSQDG-AwNKKqp6uw/zh-cn_image_0000002631323906.png?HW-CC-KV=V1&HW-CC-Date=20260709T133957Z&HW-CC-Expire=86400&HW-CC-Sign=7C0753796B453684D821AFB38C624D52BB8E2409C41BB1F78C3565B6CFE14314 "点击放大")

#### 背景知识

*   [RelativeContainer](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-relativecontainer)：相对布局组件，用于复杂场景中元素对齐的布局。
*   [vp2px](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-uicontext#vp2px12)：将vp单位的数值转换为以px为单位的数值。
*   [measureText](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-measureutils#measuretext12)：计算指定文本作为单行文本显示时的宽度。如果文本包含多行（由换行符\\n分隔），则返回其中最长的行的宽度。

#### 解决方案

1.  通过MeasureUtils的measureText方法获取组件中主体文本单行布局的长度。
2.  使用RelativeContainer容器和alignRules属性将气泡文本和主体文本组件的一侧对齐。
3.  通过offset属性将数字文本偏移，偏移距离为数字文本的宽度。

完整示例参考如下：

import { MeasureUtils } from '@kit.ArkUI';

@Entry
@Component
struct MeasurePx2vpDemo {
  textTitle: string = '发货订单';
  textNumber: string = '123';
  uiContext: UIContext = this.getUIContext();
  uiContextMeasure: MeasureUtils = this.uiContext.getMeasureUtils();
  _// 获取主体内容单行布局的长度_
  @State titleSize: SizeOptions = this.uiContextMeasure.measureTextSize({
    textContent: this.textTitle,
    fontSize: '30vp'
  });
  _// 获取数字角标单行布局的长度_
  @State numberSize: SizeOptions = this.uiContextMeasure.measureTextSize({
    textContent: this.textNumber,
    fontSize: '15vp'
  });

  build() {
    Column() {
      RelativeContainer() {
        _// 主体内容_
        Row() {
          Text(this.textTitle).fontSize('30vp');
        }.id('row1');

        _// 数字角标_
        Row() {
          Text(this.textNumber).fontSize('15vp').textAlign(TextAlign.Start).maxLines(1);
        }.id('row2')
        _// alignRules属性将组件的顶部和右侧对齐_
        .alignRules({
          top: { anchor: '\_\_container\_\_', align: VerticalAlign.Top },
          right: { anchor: '\_\_container\_\_', align: HorizontalAlign.End }
        })
        _// 通过offset属性将数字文本偏移_
        .offset({
          x: this.getUIContext().px2vp(this.numberSize.width as number),
          y: 0
        });
      }
      .width(this.getUIContext().px2vp(this.titleSize.width as number))
      .height(this.getUIContext().px2vp(this.titleSize.height as number));
    }.width('100%').height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center);
  }
}

效果如下：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/85/v3/KlOaJj6AQiCY7n-Caw61lg/zh-cn_image_0000002631324324.png?HW-CC-KV=V1&HW-CC-Date=20260709T133957Z&HW-CC-Expire=86400&HW-CC-Sign=AFA7ACBE5801D01BAA25F898396E8AF781ED3516A64E63026BF3F0B6B6D1C758 "点击放大")