如何实现自定义UI单选功能
=============

#### 问题现象

实现一个单选组件，要求：①绘制指示图标，②选中项需显示高亮状态。

效果预览：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/65/v3/pgh2B1e6QyCCgQFDE8Q0oQ/zh-cn_image_0000002658914057.png?HW-CC-KV=V1&HW-CC-Date=20260709T133911Z&HW-CC-Expire=86400&HW-CC-Sign=C8E4E020B79ADE2255F5D54173E22826A5283C783146BD5A3176D38DDE5D6B89)

#### 效果预览

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/2b/v3/lNYZA2K7T2OyTwCcCkcLxg/zh-cn_image_0000002658794107.gif?HW-CC-KV=V1&HW-CC-Date=20260709T133911Z&HW-CC-Expire=86400&HW-CC-Sign=48798C758EE83BEC9649F1D3914FFCAAA33EAFFABF8355E6F9AC76EFE33C17E8 "点击放大")

#### 背景知识

*   [Polygon](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-drawing-components-polygon)：多边形绘制组件。
*   [Stack](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-service-widget-container-stack)：堆叠容器，子组件按照顺序依次入栈，后一个子组件覆盖前一个子组件。

#### 解决方案

采用Stack容器实现层叠布局，通过@State变量控制Polygon绘制的三角形指示图标显示与隐藏状态，结合条件渲染，实现选中时的高亮切换效果。

@Entry
@Component
struct RadioPage {
  @State select: string \= 'SELECT\_OPTION\_1'; _// SELECT\_OPTION\_1__为选项一，SELECT\_OPTION\_2为选项二_

  @Builder
  commonUI(selectValue:string,imageUrl:string,context:string) {
    Stack() {
      Row() {
        Image($r(imageUrl))
          .width(40)
          .height(40)
        Text(context)
      }
      .width(150)
      .padding(5)
      .borderRadius(5)
      .border({ width: 1, color: this.select \=== selectValue ? '#ff5892de' : '#ffc4cac7' }) _//_ _根据select变量判断选中的border颜色_
      .backgroundColor(this.select \=== selectValue? '#ff5892de' : '#ffc4cac7') _//_ _根据select变量判断选中的backgroundColor颜色_
      .justifyContent(FlexAlign.Center)

      if (this.select \=== selectValue) {
      _  // 三角形指示图标_
        Polygon({ width: 20, height: 20 })
          .points(\[\[10, 10\], \[15, 0\], \[20, 10\]\])
          .fill('#ff5892de')
          .position({ top: -10, left: 10 })
      }
    }
    .onClick(() \=\> {
      this.select \= selectValue;
    })
  }

  build() {
    Column() {
      Flex({ justifyContent: FlexAlign.SpaceBetween }) {
      _  // 选项一_
        this.commonUI('SELECT\_OPTION\_1','app.media.startIcon','选项一');
     _   // 选项二_
        this.commonUI('SELECT\_OPTION\_2','app.media.startIcon','选项二');
      }
      .padding(10)
      .height(100)
      .width('100%')
    }
  }
}