管理中心
我的
您当前正在浏览新版开发者文档中心,目录分类和层级有所调整。点击左侧当前文档分类名称前的“☰”图标,可切换文档分类。 了解新版目录
问题处理与运维开发与测试问题应用框架开发UI框架UI界面如何实现文字多选框效果

如何实现文字多选框效果

问题现象

HarmonyOS中的Text控件无法手动设置isSelected参数,导致无法判断文字是否被选中。如何实现文字多选框效果?

背景知识

  • Text:显示一段文本的组件。没有其他平台isSelected参数,但是支持onClick方法。
  • onClick:点击动作触发该回调。
  • 动态属性attributeModifier可以通过Modifier对象动态修改属性,根据需要使用多态样式设置属性,组件通过attributeModifier属性绑定动态属性。
  • V2状态管理@ObservedV2与@Trace装饰器用于装饰类以及类中的属性,使得被装饰的类和属性具有深度观测的能力。

解决方案

  • 方案一:动态变量控制样式:
    具体操作步骤如下:
    1. 新建布尔类型状态控制变量isSelect,用true和false控制该Text组件是否被点击。
    2. 给Text组件添加onClick方法,点击后更改Text组件样式并生成具体业务逻辑。

    详细代码示例如下:

    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct Selected {
    4. @State isSelect1: boolean = false; // 选框1选中状态变量
    5. @State isSelect2: boolean = false; // 选框2选中状态变量
    6. build() {
    7. Row({ space: 10 }) {
    8. Text('选框1')
    9. .width(80) // 宽度
    10. .height(50) // 高度
    11. .textAlign(TextAlign.Center) // 字体居中
    12. .fontColor(this.isSelect1 ? '#000000' : '#ff0a59f7') // 字体颜色
    13. .backgroundColor(this.isSelect1 ? '#bbbbbb' : '#ffb2c9f8') // 背景颜色
    14. .border({ width: 2, color: this.isSelect1 ? Color.Transparent : '#ff0a59f7' }) // 边框
    15. .borderRadius(5) // 圆角设置
    16. .fontWeight(FontWeight.Bold) // 字体加粗
    17. .onClick(() => { // 点击改变选中状态
    18. this.isSelect1 = !this.isSelect1;
    19. });
    20. Text('选框2')
    21. .width(80) // 宽度
    22. .height(50) // 高度
    23. .textAlign(TextAlign.Center) // 字体居中
    24. .fontColor(this.isSelect2 ? '#000000' : '#ff0a59f7') // 字体颜色
    25. .backgroundColor(this.isSelect2 ? '#bbbbbb' : '#ffb2c9f8') // 背景颜色
    26. .border({ width: 2, color: this.isSelect2 ? Color.Transparent : '#ff0a59f7' }) // 边框
    27. .borderRadius(5) // 圆角设置
    28. .fontWeight(FontWeight.Bold) // 字体加粗
    29. .onClick(() => { // 点击改变选中状态
    30. this.isSelect2 = !this.isSelect2;
    31. });
    32. }
    33. .width('100%')
    34. .height('100%')
    35. .justifyContent(FlexAlign.Center)
    36. .margin({ top: -100 });
    37. }
    38. }

    效果预览:

  • 方案二:attributeModifier动态属性设置多态样式:具体操作步骤如下:
    1. 通过创建继承动态属性attributeModifier的类,设置Text组件的多态样式属性。
    2. 以@ObservedV2与@Trace装饰器装饰类和属性,以观测动态属性值的变化并刷新UI。
    3. Text组件通过点击事件,改变动态属性值,以修改Text组件的样式属性。

    详细代码示例如下:

    收起
    自动换行
    深色代码主题
    复制
    1. import { LengthUnit } from '@kit.ArkUI';
    2. // 创建动态属性类,并以@ObservedV2与@Trace装饰器装饰
    3. @ObservedV2
    4. class TextCustomStyle implements AttributeModifier<TextAttribute> {
    5. // 动态属性值
    6. @Trace public isSelected: boolean = false;
    7. // 设置组件样式
    8. applyNormalAttribute(instance: TextAttribute): void {
    9. // 根据动态属性值的不同,设置Text组件的不同样式属性
    10. if (this.isSelected) {
    11. instance.fontColor(Color.Blue);
    12. instance.backgroundColor('#00bfff');
    13. instance.border({
    14. width: 0.5,
    15. color: Color.Blue,
    16. radius: 18
    17. });
    18. } else {
    19. instance.fontColor(Color.Black);
    20. instance.backgroundColor(Color.Gray);
    21. instance.border({
    22. radius: 18
    23. });
    24. }
    25. }
    26. }
    27. @Entry
    28. @Component
    29. struct TextMultiSelect {
    30. arr: string[] = ['Sports', 'Games', 'Programming'];
    31. @State textStyles: TextCustomStyle[] = [];
    32. @State selectedItem: string[] = [];
    33. aboutToAppear(): void {
    34. // 每个Text组件分别绑定属性类
    35. for (let i = 0; i < this.arr.length; i++) {
    36. this.textStyles.push(new TextCustomStyle());
    37. }
    38. }
    39. build() {
    40. Column() {
    41. Flex({
    42. direction: FlexDirection.Row,
    43. justifyContent: FlexAlign.Center,
    44. space: {
    45. main: { value: 5, unit: LengthUnit.VP },
    46. cross: { value: 10, unit: LengthUnit.VP }
    47. }
    48. }) {
    49. ForEach(this.arr, (item: string, index: number) => {
    50. Text(item)
    51. .height(50)
    52. .fontSize('18fp')
    53. .padding(5)
    54. // 设置动态属性
    55. .attributeModifier(this.textStyles[index])
    56. .onClick(() => {
    57. // 改变属性类的属性值
    58. this.textStyles[index].isSelected = !this.textStyles[index].isSelected;
    59. if (this.textStyles[index].isSelected) {
    60. // 保存选项
    61. this.selectedItem.push(item);
    62. } else {
    63. // 删除选项
    64. let idx = this.selectedItem.indexOf(item);
    65. let arrFront = this.selectedItem.slice(0, idx);
    66. let arrBack = this.selectedItem.slice(idx + 1);
    67. this.selectedItem = arrFront.concat(arrBack);
    68. }
    69. });
    70. });
    71. }
    72. .height('auto')
    73. .width('100%');
    74. // 选项展示,无选项时显示None
    75. Text('Selected Item: ' + (this.selectedItem.length === 0 ? 'None' : this.selectedItem.join(', ')));
    76. }
    77. .justifyContent(FlexAlign.SpaceEvenly)
    78. .height('50%')
    79. .width('100%');
    80. }
    81. }

    效果预览:

    • 方案三:其他多选框实现:
      • 若要实现更标准的切换选框,推荐使用Toggle组件:Toggle组件提供状态按钮样式、勾选框样式和开关样式,一般用于两种状态之间的切换。
      • 若要实现更标准的多选框,推荐使用Checkbox组件:Checkbox提供多选框组件,通常用于某选项的打开或关闭。

总结

上述方案适用场景总结如下:

展开

方法

核心特点

适用场景

动态变量控制样式

完全自定义样式(颜色、背景、字体等),需手动管理状态和样式逻辑

需要高度个性化的外观(如自定义图标、复杂背景);轻量多选(选项数量少)

attributeModifier动态属性设置多态样式

动态绑定属性,代码更简洁,支持批量样式修改(如同时改颜色和字体大小)

需要动态修改多个样式属性;样式逻辑需复用(如多个组件共享同一种动态样式规则)

Checkbox组件(非文字组件场景)

非文字框场景下,可以自动管理选中状态和样式(如勾选图标、默认颜色)

标准多选场景(如表单勾选、选项筛选);需要系统级一致性的交互体验

Toggle组件(非文字组件场景)

本质是开关,非文字框场景下,需自定义样式模拟多选;交互更接近“开启/关闭”而非“选中/未选中”

轻量多选(如快速切换多个开关状态);需要开关样式的场景(如夜间模式切换)