视频演示地址:

https://www.bilibili.com/video/BV1jomdBBE4H/
在这里插入图片描述

📋 目录


概述

ButtonGroup 是控件库中的按钮组组件,将多个按钮组合在一起,支持单选和多选两种模式,适用于选项选择、筛选、状态切换等场景。

设计理念

按钮组采用统一视觉设计,具有以下特点:

  1. 组合设计:多个按钮无缝连接,形成统一的视觉整体
  2. 模式灵活:支持单选(single)和多选(multiple)两种模式
  3. 尺寸多样:支持 small、medium、large 三种尺寸
  4. 状态清晰:选中状态使用主色背景,未选中状态使用次要背景
  5. 品牌标识:左下角自动包含品牌标识(圆圈红字"PC")
  6. 主题统一:所有样式配置都在代码中,方便定制

适用场景

  • 筛选条件:时间筛选、状态筛选、类型筛选
  • 选项选择:单选选项、多选选项
  • 状态切换:启用/禁用、显示/隐藏
  • 标签选择:分类标签、属性标签

特性

✨ 核心特性

  • 单选模式:支持单选模式,只能选择一个选项
  • 多选模式:支持多选模式,可以选择多个选项
  • 图标支持:支持文字图标(textIcon)和图片图标(icon)
  • 多种尺寸:支持 small、medium、large 三种尺寸
  • 禁用状态:支持整体禁用和单项禁用
  • 品牌标识:自动包含左下角品牌标识
  • 主题配置:所有样式都可通过代码配置

🎨 视觉特点

  • 选中状态:主色背景 + 白色文字
  • 未选中状态:次要背景 + 主色文字
  • 禁用状态:灰色背景 + 灰色文字 + 50% 透明度
  • 无缝连接:按钮之间无缝连接,形成统一整体
  • 圆角设计:整体使用圆角,内部按钮无圆角

快速开始

基础用法

import { ButtonGroup, ButtonGroupItem } from '../components/base'

@Entry
@Component
struct MyPage {
  @State selectedValue: string | number = 'option1'

  private items: ButtonGroupItem[] = [
    { label: '选项1', value: 'option1' },
    { label: '选项2', value: 'option2' },
    { label: '选项3', value: 'option3' }
  ]

  build() {
    Column({ space: 20 }) {
      // 单选模式
      ButtonGroup({
        items: this.items,
        mode: 'single'
      })
      
      // 多选模式
      ButtonGroup({
        items: this.items,
        mode: 'multiple'
      })
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .justifyContent(FlexAlign.Center)
  }
}

关于状态管理

ButtonGroup 使用内部状态管理选中值。如果需要外部控制选中值,可以通过监听点击事件或使用状态管理来实现。


API 参考

Props

属性名 类型 默认值 说明
items ButtonGroupItem[] [] 按钮项列表(必需)
mode 'single' | 'multiple' 'single' 选择模式:单选或多选
buttonSize 'small' | 'medium' | 'large' 'medium' 按钮尺寸
showBrand boolean true 是否显示品牌标识
disabled boolean false 是否禁用整个按钮组

ButtonGroupItem 接口

属性名 类型 默认值 说明
label string - 按钮文字(必需)
value string | number - 按钮值(必需)
disabled boolean? undefined 是否禁用该项
icon ResourceStr? undefined 图片图标(可选)
textIcon string? undefined 文字图标(可选,优先级高于 icon)

尺寸规格

尺寸 按钮高度 字体大小 图标大小 内边距
small 28vp 12vp 14vp 12vp(左右)
medium 36vp 14vp 16vp 16vp(左右)
large 44vp 16vp 20vp 20vp(左右)

使用示例

1. 基础单选按钮组

@Entry
@Component
struct ButtonGroupExample1 {
  private items: ButtonGroupItem[] = [
    { label: '选项1', value: 'option1' },
    { label: '选项2', value: 'option2' },
    { label: '选项3', value: 'option3' }
  ]

  build() {
    Column({ space: 15 }) {
      ButtonGroup({
        items: this.items,
        mode: 'single'
      })
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .justifyContent(FlexAlign.Center)
  }
}

2. 多选按钮组

@Entry
@Component
struct ButtonGroupExample2 {
  private items: ButtonGroupItem[] = [
    { label: '选项1', value: 'option1' },
    { label: '选项2', value: 'option2' },
    { label: '选项3', value: 'option3' }
  ]

  build() {
    Column({ space: 15 }) {
      ButtonGroup({
        items: this.items,
        mode: 'multiple'
      })
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .justifyContent(FlexAlign.Center)
  }
}

3. 带图标的按钮组

@Entry
@Component
struct ButtonGroupExample3 {
  private items: ButtonGroupItem[] = [
    { label: '全部', value: 'all', textIcon: 'A' },
    { label: '待处理', value: 'pending', textIcon: 'P' },
    { label: '已完成', value: 'completed', textIcon: '√' }
  ]

  build() {
    Column({ space: 15 }) {
      ButtonGroup({
        items: this.items,
        mode: 'single'
      })
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .justifyContent(FlexAlign.Center)
  }
}

4. 不同尺寸

@Entry
@Component
struct ButtonGroupExample4 {
  private items: ButtonGroupItem[] = [
    { label: '小', value: 'small' },
    { label: '中', value: 'medium' },
    { label: '大', value: 'large' }
  ]

  build() {
    Column({ space: 20 }) {
      ButtonGroup({
        items: this.items,
        mode: 'single',
        buttonSize: 'small'
      })
      
      ButtonGroup({
        items: this.items,
        mode: 'single',
        buttonSize: 'medium'
      })
      
      ButtonGroup({
        items: this.items,
        mode: 'single',
        buttonSize: 'large'
      })
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .justifyContent(FlexAlign.Center)
  }
}

5. 禁用状态

@Entry
@Component
struct ButtonGroupExample5 {
  private items: ButtonGroupItem[] = [
    { label: '可用', value: 'available' },
    { label: '不可用', value: 'unavailable', disabled: true },
    { label: '维护中', value: 'maintenance' }
  ]

  build() {
    Column({ space: 20 }) {
      // 整个按钮组禁用
      ButtonGroup({
        items: this.items,
        mode: 'single',
        disabled: true
      })
      
      Divider()
        .margin({ top: 20, bottom: 20 })
      
      // 部分按钮禁用
      ButtonGroup({
        items: this.items,
        mode: 'single'
      })
    }
    .width('100%')
    .height('100%')
    .padding(20)
    .justifyContent(FlexAlign.Center)
  }
}

6. 筛选场景

@Entry
@Component
struct FilterExample {
  build() {
    Column({ space: 20 }) {
      // 时间筛选
      Column({ space: 10 }) {
        Text('时间筛选:')
          .fontSize(16)
          .fontColor('#111827')
          .width('100%')
        
        ButtonGroup({
          items: [
            { label: '全部', value: 'all' },
            { label: '今天', value: 'today' },
            { label: '本周', value: 'week' },
            { label: '本月', value: 'month' }
          ],
          mode: 'single',
          buttonSize: 'medium'
        })
      }
      .width('100%')
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

7. 状态选择场景

@Entry
@Component
struct StatusExample {
  build() {
    Column({ space: 20 }) {
      // 订单状态(多选)
      Column({ space: 10 }) {
        Text('订单状态(多选):')
          .fontSize(16)
          .fontColor('#111827')
          .width('100%')
        
        ButtonGroup({
          items: [
            { label: '待付款', value: 'unpaid', textIcon: 'P' },
            { label: '待发货', value: 'unshipped', textIcon: 'S' },
            { label: '已发货', value: 'shipped', textIcon: '√' },
            { label: '已完成', value: 'completed', textIcon: 'C' }
          ],
          mode: 'multiple',
          buttonSize: 'medium'
        })
      }
      .width('100%')
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }
}

主题配置

ButtonGroup 的所有样式都通过 ComponentTheme 配置,所有配置都在代码中,不依赖JSON文件。

修改默认颜色

import { ComponentTheme } from '../theme/ComponentTheme'

// 修改主色(影响选中状态的背景色)
ComponentTheme.PRIMARY_COLOR = '#007AFF'

// 修改次要背景色(影响未选中状态的背景色)
ComponentTheme.BACKGROUND_SECONDARY = '#F5F5F5'

// 修改边框颜色
ComponentTheme.BORDER_COLOR = '#E5E5E5'

// 修改圆角
ComponentTheme.BORDER_RADIUS = 8

批量配置

import { ComponentTheme } from '../theme/ComponentTheme'

// 使用 setTheme 方法批量配置
ComponentTheme.setTheme({
  primaryColor: '#007AFF',
  borderRadius: 8,
  spacing: 16
})

最佳实践

1. 模式选择

推荐:根据使用场景选择模式

  • 单选模式(single):用于互斥选项,如时间筛选、状态切换
  • 多选模式(multiple):用于可多选的选项,如标签选择、属性筛选

2. 尺寸选择

  • small:用于紧凑空间、工具栏
  • medium:默认尺寸,适用于大多数场景
  • large:用于重要操作或大屏幕显示

3. 选项数量

  • 建议选项数量在 2-5 个之间
  • 选项过多时考虑使用下拉菜单或其他组件
  • 选项文字保持简洁,避免过长

4. 图标使用

  • 使用文字图标(textIcon)确保兼容性
  • 图标应与文字含义相关
  • 保持图标风格统一

5. 禁用状态

  • 使用整体禁用(disabled)控制整个按钮组
  • 使用单项禁用(item.disabled)控制单个选项
  • 禁用状态应清晰可见

6. 响应式设计

  • 在小屏幕上考虑使用 smaller 尺寸
  • 保持按钮之间的合理间距
  • 确保触摸目标足够大(至少 28vp)

常见问题

Q1: ButtonGroup 和其他按钮有什么区别?

A: 主要区别在于使用场景:

  • PrimaryButton/SecondaryButton/TextButton/IconButton:单个按钮,用于操作
  • ButtonGroup:多个按钮组合,用于选项选择、筛选

ButtonGroup 更适合需要从多个选项中选择的场景。

Q2: 什么时候使用单选,什么时候使用多选?

A: 根据业务需求选择:

  • 单选模式(single):选项互斥,只能选择一个,如时间筛选、状态切换
  • 多选模式(multiple):选项不互斥,可以选择多个,如标签选择、属性筛选

Q3: 如何获取选中的值?

A: ButtonGroup 使用内部状态管理。如果需要外部获取选中值,可以通过以下方式:

  1. 监听点击事件:在按钮点击时获取值
  2. 状态管理:使用全局状态管理(如 Redux、MobX)
  3. 自定义事件:创建自定义事件系统

Q4: 可以动态更新选项吗?

A: 可以。通过更新 items 数组来动态更新选项:

@State items: ButtonGroupItem[] = [
  { label: '选项1', value: 'option1' }
]

// 动态添加选项
this.items.push({ label: '选项2', value: 'option2' })
this.items = [...this.items]  // 触发更新

Q5: 如何自定义按钮样式?

A: 可以通过 ComponentTheme 自定义全局样式:

ComponentTheme.PRIMARY_COLOR = '#34C759'  // 选中状态背景色
ComponentTheme.BACKGROUND_SECONDARY = '#F0F0F0'  // 未选中状态背景色
ComponentTheme.BORDER_RADIUS = 12  // 圆角大小

Q6: 按钮组可以垂直排列吗?

A: 当前版本支持水平排列。如果需要垂直排列,可以:

  1. 使用多个 ButtonGroup 垂直排列
  2. 自定义实现垂直布局的按钮组

总结

ButtonGroup 是控件库中的按钮组组件,具有以下核心特性:

  1. 组合设计:多个按钮无缝连接,形成统一整体
  2. 模式灵活:支持单选和多选两种模式
  3. 尺寸多样:三种尺寸满足不同场景需求
  4. 功能完整:支持图标、禁用等多种功能
  5. 易于使用:简单的 API,开箱即用
  6. 主题配置:所有样式都可通过代码配置
  7. 品牌标识:自动包含品牌标识,保持视觉统一

关键要点

  • ✅ 使用 mode 属性选择单选或多选模式
  • ✅ 使用 buttonSize 属性选择合适尺寸
  • ✅ 使用 items 属性配置按钮项
  • ✅ 使用 disabled 属性控制按钮组状态
  • ✅ 使用 textIconicon 添加图标
  • ✅ 通过 ComponentTheme 自定义全局样式

适用场景

  • 筛选条件选择
  • 选项选择
  • 状态切换
  • 标签选择
  • 属性筛选

下一篇预告:TextInput(文本输入框)详解


本文档属于《鸿蒙PC UI控件库开发系列文章》第6篇

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐