HarmonyOS鸿蒙Next中使用onAreaChange与Polygon实现动态跟随角标

HarmonyOS鸿蒙Next中使用onAreaChange与Polygon实现动态跟随角标 如何使用 onAreaChange 与 Polygon ,通过计算实现动态跟随角标?

4 回复

666

更多关于HarmonyOS鸿蒙Next中使用onAreaChange与Polygon实现动态跟随角标的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


实现效果

动态跟随箭头演示

使用场景

在IM 聊天中,我们经常会使用针对发送方和接收方的消息气泡,箭头需指向头像一侧或居中。

另外在一些需要跟随鼠标或手指位置的 Tooltip,箭头需动态调整指向的场景也极其常见。

实现思路

第一步:构建气泡结构,使用 Column 或 Stack 作为气泡容器,内部包含 Text 组件,设置 alignItems 为 HorizonAlign.Center,使文字内容撑开容器宽度。

第二步:监听尺寸变化,在气泡容器上添加 .onAreaChange 回调。

第三步:计算箭头位置,在回调中获取 newValue.width,计算公式:ArrowOffsetX = (ContainerWidth / 2) - (ArrowWidth / 2)。

第四步:渲染动态箭头,使用 Polygon (多边形) 组件绘制一个三角形,利用 .translate({ x: this.arrowOffset }) 属性,根据状态变量实时更新箭头的水平位置。

完整实现代码

@Entry
@Component
struct DynamicBubbleDemo {
  // 控制气泡内容的文本
  @State message: string = '点击按钮切换文字长度';

  // 控制箭头的 X 轴偏移量
  @State arrowOffset: number = 0;

  build() {
    Column() {
      Text("动态跟随箭头演示")
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 60, bottom: 40 })

      // 使用相对布局,将箭头放在上方,气泡放在下方
      Stack({ alignContent: Alignment.Top }) {

        // 顶部箭头 (使用 Polygon 绘制三角形)
        Polygon({ width: 20, height: 10 })
          .points([[0, 0], [10, 10], [20, 0]])
          .fill('#0A59F7')
          .translate({ x: this.arrowOffset })
          .margin({ top: 0 })

        // 气泡主体
        Column() {
          Text(this.message)
            .fontSize(16)
            .fontColor('#FFFFFF')
            .padding(12)
            .width('fitContent')
        }
        .backgroundColor('#0A59F7')
        .borderRadius(12)
        .padding({ left: 16, right: 16, top: 12, bottom: 12 })
        .margin({ top: 10 }) 
        .shadow({ radius: 10, color: '#1A000000', offsetY: 4 })
        .onAreaChange((oldValue: Area, newValue: Area) => {
          // 当气泡宽度发生变化时触发
          const width = newValue.width as number;

          // 计算居中偏移量:箭头宽度的一半是 10,所以不需要额外除以 2
          // 若箭头 width=20,则中心在 10。
          // 目标位置:气泡中心宽度 - 箭头一半宽度
          // 简单算法:居中位置 = 宽度 * 0.5 - 10 (箭头半径)
          this.arrowOffset = (width * 0.5) - 10;
        })
      }
      .width('100%')
      .height(100)

      Blank()

      Row({ space: 20 }) {
        Button("短文字")
          .onClick(() => {
            this.message = "短";
          })

        Button("长文字测试")
          .onClick(() => {
            this.message = "这是一段很长的文字,用来测试箭头是否会自动居中显示。";
          })
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F1F3F5')
  }
}

在HarmonyOS Next中,使用onAreaChangePolygon实现动态跟随角标,主要涉及以下步骤:

  1. 使用Polygon组件绘制多边形区域。
  2. 通过onAreaChange事件监听多边形区域变化,获取其位置和大小信息。
  3. 根据onAreaChange返回的区域信息,动态计算并更新角标的位置,使其跟随多边形移动或缩放。

关键点在于利用onAreaChange的回调数据实时调整角标的布局属性,实现精准跟随。

在HarmonyOS Next中,使用onAreaChangePolygon实现动态跟随角标,核心思路是通过监听目标区域变化,实时计算并更新角标位置。以下是具体实现方法:

1. 监听目标区域变化

使用onAreaChange监听目标组件(如图片、视图)的区域变化,获取其位置和大小信息。

@State targetRect: Rect = { width: 0, height: 0, x: 0, y: 0 };

// 在目标组件上添加监听
Component()
  .onAreaChange((oldRect, newRect) => {
    this.targetRect = newRect;
  })

2. 定义Polygon角标

使用Polygon绘制角标图形,通常是一个三角形或自定义形状,并通过状态变量控制其位置。

@State badgePosition: Position = { x: 0, y: 0 };

Polygon()
  .points(this.getBadgePoints()) // 根据位置计算顶点坐标
  .fill(Color.Red)
  .position(this.badgePosition)

3. 动态计算角标位置

onAreaChange回调中,根据目标区域信息计算角标应放置的位置(如右上角)。

onAreaChange((oldRect, newRect) => {
  this.targetRect = newRect;
  // 计算角标位置:目标区域右上角偏移
  this.badgePosition = {
    x: newRect.x + newRect.width - BADGE_SIZE,
    y: newRect.y - BADGE_SIZE / 2
  };
})

4. 优化性能

  • 使用@State管理位置数据,确保UI同步更新。
  • 若跟随目标移动频繁,可考虑节流计算,避免过度渲染。

注意事项

  • onAreaChange在组件布局变化时触发,需注意性能影响。
  • Polygon的顶点坐标需基于位置动态计算,确保角标方向正确(如三角形指向目标)。

此方案通过区域监听与图形绘制结合,实现了角标对目标元素的动态跟随,适用于标记、通知等场景。

回到顶部