鸿蒙组件——Checkbox和CheckboxGroup

1,229 阅读4分钟

一、Checkbox

1.1 多选框

场景:Checkbox用于一种常用的用户界面元素,用于表示二进制选择状态,即“选中”或“未选中”。

image.png

2.2 参数CheckboxOptions说明

名称类型必填描述
namestring用于指定多选框名称。一般结合CheckboxGroup一起使用
groupstring用于指定多选框所属群组的名称(即所属CheckboxGroup的名称)。

2.3 常用属性

名称参数类型描述
selectboolean设置多选框是否选中。 默认值:false 从API version 9开始,该接口支持在ArkTS卡片中使用。 从API version 10开始,该属性支持$$双向绑定变量。
selectedColorResourceColor设置多选框选中状态颜色。 说明: 默认值:$r(‘sys.color.ohos_id_color_text_primary_activated’)。 异常值按照默认值处理。 从API version 9开始,该接口支持在ArkTS卡片中使用。
unselectedColorResourceColor设置多选框非选中状态边框颜色。
shapeCheckBoxShape设置CheckBox组件形状, 包括圆形和圆角方形。 说明: 默认值:CheckBoxShape.CIRCLE。
..........

2.4. CheckboxGroup

如果要控制多个 Checkbox 的选中状态,可以通过CheckBoxGroup来实现

2.4.1. 基本使用

CheckboxGroup(options?: CheckboxGroupOptions)

参数说明(CheckboxGroupOptions)

名称类型必填说明
groupstring群组名称。 说明: 多个相同群组名称的CheckboxGroup,仅第一个CheckboxGroup生效。

常用属性

名称参数类型描述
selectAllboolean设置是否全选。 默认值:false,若同组的Checkbox设置了select属性,则Checkbox的优先级高。 该属性支持$$,双向绑定变量。
selectedColorResourceColor设置被选中或部分选中状态的颜色。
unselectedColorResourceColor设置非选中状态边框颜色。

二、实例实现

2.1 实现购物车购物物品总价钱计算 如图:

image.png

2.2 静态结构

image.png

2.2.1 静态结构代码

interface GoodInfo {
  id: number // 商品ID
  name: string // 商品名称
  img: ResourceStr// 商品图片
  price: number// 商品价格
  count: number// 商品数量
}


@Entry
@Component
struct CartPage {
  goodList: GoodInfo[] = [
    {
      id: 1,
      name: 'CP  正大 鲜鸡蛋 30枚 1.59kg 早餐食材 优质蛋白  简装 年货礼盒',
      img: 'https://img10.360buyimg.com/n2/s240x240_jfs/t1/123263/8/18451/99918/5fadf6d2E23e7dd22/8ba19066638ac30c.jpg!q70.jpg.webp',
      price: 25.8,
      count: 2
    },
    {
      id: 2,
      name: '小汤山 北京 西兰花 270g 基地直供新鲜蔬菜',
      img: 'https://img14.360buyimg.com/n2/s240x240_jfs/t1/169777/20/30573/169612/63439079E163426f6/918bf9a3daff559a.jpg!q70.jpg.webp',
      price: 14.9,
      count: 3
    },
    {
      id: 3,
      name: '塞莫诗 丁腈手套加长款30只/包 加厚型 防油防水耐污 白色中号',
      img: 'https://img10.360buyimg.com/n2/s240x240_jfs/t1/98273/24/30795/51511/641a9523F88afbc89/7ec4f5a970449aaf.jpg!q70.jpg.webp',
      price: 39.9,
      count: 3
    },
    {
      id: 4,
      name: '努比亚(nubia)红魔9 Pro+全面屏下游戏手机 16GB+512GB氘锋透明暗夜 骁龙8Gen3 165W快充 5500mAh 5G电竞手机',
      img: 'https://img11.360buyimg.com/n2/s240x240_jfs/t1/154052/34/22342/2570546/65f39e22F565a8c81/9fc2c1c50e7abe57.jpg!q70.jpg.webp',
      price: 5999,
      count: 2
    },
    {
      id: 5,
      name: '炊大皇 炒锅 304不锈钢炒菜锅煎锅 平底不粘炒锅32cm 可立可视盖不挑灶',
      img: 'https://img13.360buyimg.com/n2/s240x240_jfs/t1/195539/22/41621/175614/65f3fdecF15a476ce/c9ba416cbce6d9cc.jpg!q70.jpg.webp',
      price: 139,
      count: 3
    }, {
    id: 6,
    name: '西贝莜面村梅菜扣肉200g 肥瘦相间五花肉酥软不腻 预制菜 新包装',
    img: 'https://img10.360buyimg.com/n2/s240x240_jfs/t1/168770/10/43511/163526/65d45a8aF9e865e6b/66a9d6484d8ab6e3.jpg!q70.jpg.webp',
    price: 29.9,
    count: 4
  }
  ]

  build() {
    Column() {
      // 商品列表
      List() {
        ListItem() {
          Row({ space: 10 }) {
            Checkbox()
              .selectedColor('#eb4646')
            Image('https://img11.360buyimg.com/n2/s240x240_jfs/t1/154052/34/22342/2570546/65f39e22F565a8c81/9fc2c1c50e7abe57.jpg!q70.jpg.webp')
              .width(100)
              .borderRadius(10)
            Column() {
              Text('商品名')
                .maxLines(2)
                .textOverflow({ overflow: TextOverflow.Ellipsis })
              Blank()
              Row() {
                Text(`¥10.0`)
                  .fontColor(Color.Red)
                  .fontSize(20)
                Blank()
                Text(`x 10`)
                  .fontColor(Color.Gray)
                  .fontSize(14)
              }
              .width('100%')
            }
            .height('100%')
            .layoutWeight(1)

          }
          .height(110)
          .padding(10)
        }
      }
      .divider({ strokeWidth: 1, startMargin: 40, endMargin: 20 })
      .edgeEffect(EdgeEffect.Fade)

      .layoutWeight(1)

      // 结算
      Row() {
        CheckboxGroup()
          .selectedColor('#d8534c')

        Text('全选')
        Text() {
          Span('合计')
          Span(`¥0.0`)
            .fontColor('#d8534c')
        }
        .layoutWeight(1)
        .textAlign(TextAlign.Center)

        Button('结算')
          .type(ButtonType.Normal)
          .height('100%')
          .width(120)
          .backgroundColor('#d8534c')
      }
      .height(50)
      .backgroundColor(Color.White)
      .width('100%')


    }
    .height('100%')

  }
}

2.3 业务需求

2.3.1 将全部的商品信息全部渲染出来

技术1: ForEach来遍历数组中的元素来渲染
技术2:CheckboxGroup中有个Onchange()事件来实现用户点击了哪个商品

2.3.2 具体实现

1.1 遍历数组
1.2 将数据渲染到页面上
     // 商品列表
      List() {
        ForEach(this.goodList,(item:GoodInfo)=>{
          ListItem() {
            Row({ space: 10 }) {

              Checkbox({name:item.id.toString(),group:'foods'})
                .selectedColor('#eb4646')

              Image(item.img)
                .width(100)
                .borderRadius(10)
              Column() {
                Text(item.name)
                  .maxLines(2)
                  .textOverflow({ overflow: TextOverflow.Ellipsis })
                Blank()
                Row() {
                  Text(${item.price}`)
                    .fontColor(Color.Red)
                    .fontSize(20)
                  Blank()
                  Text(`x ${item.count}`)
                    .fontColor(Color.Gray)
                    .fontSize(14)
                }
                .width('100%')
              }
              .height('100%')
              .layoutWeight(1)

            }
            .height(110)
            .padding(10)
          }
        })

      }
      .divider({ strokeWidth: 1, startMargin: 40, endMargin: 20 })
      .edgeEffect(EdgeEffect.Fade)
      .layoutWeight(1)

按照上面的操作后你就会得到下面渲染后的页面效果了:

image.png

三、计算总计

此时你已经将数据全部渲染到页面上,下一步需要考虑用户点击选择框时,算出总价格是多少? 那么根据技术点2可以解决用户选择了那些商品,当用户点击选择框时就会触发Onchange()这个事件,然后根据触发事件返回的name值去匹配数组中元素中的name值,将这些商品筛选出来在进行相加就可以了。

3.1 调用Onchange()事件

   CheckboxGroup({group:'foods'})
          .selectedColor('#d8534c')
          .onChange((res)=>{
            let news = this.goodList.filter((item)=>{
              return res.name.includes(item.id.toString())
            })
            this.sum = 0
             news.forEach((item)=>{
              return this.sum+=item.price*item.count
            })

3.2 完整代码


interface GoodInfo {
  id: number
  name: string
  img: ResourceStr
  price: number
  count: number
}


@Entry
@Component
struct CartPage {
  goodList: GoodInfo[] = [
    {
      id: 1,
      name: 'CP  正大 鲜鸡蛋 30枚 1.59kg 早餐食材 优质蛋白  简装 年货礼盒',
      img: 'https://img10.360buyimg.com/n2/s240x240_jfs/t1/123263/8/18451/99918/5fadf6d2E23e7dd22/8ba19066638ac30c.jpg!q70.jpg.webp',
      price: 25.8,
      count: 2
    },
    {
      id: 2,
      name: '小汤山 北京 西兰花 270g 基地直供新鲜蔬菜',
      img: 'https://img14.360buyimg.com/n2/s240x240_jfs/t1/169777/20/30573/169612/63439079E163426f6/918bf9a3daff559a.jpg!q70.jpg.webp',
      price: 14.9,
      count: 3
    },
    {
      id: 3,
      name: '塞莫诗 丁腈手套加长款30只/包 加厚型 防油防水耐污 白色中号',
      img: 'https://img10.360buyimg.com/n2/s240x240_jfs/t1/98273/24/30795/51511/641a9523F88afbc89/7ec4f5a970449aaf.jpg!q70.jpg.webp',
      price: 39.9,
      count: 3
    },
    {
      id: 4,
      name: '努比亚(nubia)红魔9 Pro+全面屏下游戏手机 16GB+512GB氘锋透明暗夜 骁龙8Gen3 165W快充 5500mAh 5G电竞手机',
      img: 'https://img11.360buyimg.com/n2/s240x240_jfs/t1/154052/34/22342/2570546/65f39e22F565a8c81/9fc2c1c50e7abe57.jpg!q70.jpg.webp',
      price: 5999,
      count: 2
    },
    {
      id: 5,
      name: '炊大皇 炒锅 304不锈钢炒菜锅煎锅 平底不粘炒锅32cm 可立可视盖不挑灶',
      img: 'https://img13.360buyimg.com/n2/s240x240_jfs/t1/195539/22/41621/175614/65f3fdecF15a476ce/c9ba416cbce6d9cc.jpg!q70.jpg.webp',
      price: 139,
      count: 3
    }, {
    id: 6,
    name: '西贝莜面村梅菜扣肉200g 肥瘦相间五花肉酥软不腻 预制菜 新包装',
    img: 'https://img10.360buyimg.com/n2/s240x240_jfs/t1/168770/10/43511/163526/65d45a8aF9e865e6b/66a9d6484d8ab6e3.jpg!q70.jpg.webp',
    price: 29.9,
    count: 4
  }
  ]
  @State sum:number = 0

  build() {
    Column() {
      // 顶部图片
      // Image($r('app.media.cart_top'))
      //   .width('100%')
      // 商品列表
      List() {
        ForEach(this.goodList,(item:GoodInfo)=>{
          ListItem() {
            Row({ space: 10 }) {

              Checkbox({name:item.id.toString(),group:'foods'})
                .selectedColor('#eb4646')

              Image(item.img)
                .width(100)
                .borderRadius(10)
              Column() {
                Text(item.name)
                  .maxLines(2)
                  .textOverflow({ overflow: TextOverflow.Ellipsis })
                Blank()
                Row() {
                  Text(`¥${item.price}`)
                    .fontColor(Color.Red)
                    .fontSize(20)
                  Blank()
                  Text(`x ${item.count}`)
                    .fontColor(Color.Gray)
                    .fontSize(14)
                }
                .width('100%')
              }
              .height('100%')
              .layoutWeight(1)

            }
            .height(110)
            .padding(10)
          }
        })

      }
      .divider({ strokeWidth: 1, startMargin: 40, endMargin: 20 })
      .edgeEffect(EdgeEffect.Fade)
      .layoutWeight(1)


      // 结算
      Row() {
        CheckboxGroup({group:'foods'})
          .selectedColor('#d8534c')
          .onChange((res)=>{
            let news = this.goodList.filter((item)=>{
              return res.name.includes(item.id.toString())
            })
            this.sum = 0
             news.forEach((item)=>{
              return this.sum+=item.price*item.count
            })

          })

        Text('全选')
        Text() {
          Span('合计')
          Span(`¥${this.sum}`)
            .fontColor('#d8534c')
        }
        .layoutWeight(1)
        .textAlign(TextAlign.Center)

        Button('结算')
          .type(ButtonType.Normal)
          .height('100%')
          .width(120)
          .backgroundColor('#d8534c')
      }
      .height(50)
      .backgroundColor(Color.White)
      .width('100%')


    }
    .height('100%')

  }
}

这样就可以实现用户选择商品时计算商品的总价