img

一、案例介绍

本案例将展示Select组件的高级选择功能和自定义样式实现,通过一个商品筛选器的示例,展示如何构建功能丰富、外观精美的选择器界面。

二、代码实现

@Entry
@Component
struct SelectAdvancedExample {
  @State selectedCategory: string = ''
  @State selectedSubCategory: string = ''
  @State selectedBrand: string = ''
  @State selectedPrice: string = ''

  @State categoryIndex: number = -1
  @State subCategoryIndex: number = -1
  @State brandIndex: number = -1
  @State priceIndex: number = -1

  @State subCategories: string[] = []
  @State brands: string[] = []

  private readonly categories: string[] = ['手机数码', '电脑办公', '家用电器', '服装鞋包']
  private readonly categoryMap: Map<string, string[]> = new Map([
    ['手机数码', ['手机', '平板', '智能手表', '耳机']],
    ['电脑办公', ['笔记本', '台式机', '显示器', '打印机']],
    ['家用电器', ['电视', '空调', '冰箱', '洗衣机']],
    ['服装鞋包', ['男装', '女装', '运动', '箱包']]
  ])
  private readonly brandMap: Map<string, string[]> = new Map([
    ['手机', ['华为', '苹果', '小米', '三星']],
    ['平板', ['华为', '苹果', '小米', '联想']],
    ['笔记本', ['联想', '华为', '戴尔', '惠普']],
    ['电视', ['海信', '小米', 'TCL', '索尼']]
  ])
  private readonly priceRanges: string[] = [
    '0-1000元',
    '1000-3000元',
    '3000-5000元',
    '5000元以上'
  ]

  build() {
    Column() {
      Text('商品筛选')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 20 })

      // 一级分类
      this.SelectItem(
        '商品分类:',
        this.selectedCategory || '请选择分类',
        this.categories,
        this.categoryIndex,
        (index: number) => {
          this.categoryIndex = index
          this.selectedCategory = this.categories[index]
          // 更新二级分类
          this.subCategories = this.categoryMap.get(this.selectedCategory) || []
          // 重置后续选择
          this.resetSubSelections()
        }
      )

      // 二级分类
      if (this.subCategories.length > 0) {
        this.SelectItem(
          '子分类:',
          this.selectedSubCategory || '请选择子分类',
          this.subCategories,
          this.subCategoryIndex,
          (index: number) => {
            this.subCategoryIndex = index
            this.selectedSubCategory = this.subCategories[index]
            // 更新品牌
            this.brands = this.brandMap.get(this.selectedSubCategory) || []
            // 重置后续选择
            this.resetBrandAndPrice()
          }
        )
      }

      // 品牌选择
      if (this.brands.length > 0) {
        this.SelectItem(
          '品牌:',
          this.selectedBrand || '请选择品牌',
          this.brands,
          this.brandIndex,
          (index: number) => {
            this.brandIndex = index
            this.selectedBrand = this.brands[index]
            this.resetPrice()
          }
        )
      }

      // 价格区间
      if (this.selectedBrand) {
        this.SelectItem(
          '价格区间:',
          this.selectedPrice || '请选择价格区间',
          this.priceRanges,
          this.priceIndex,
          (index: number) => {
            this.priceIndex = index
            this.selectedPrice = this.priceRanges[index]
          }
        )
      }

      // 筛选结果预览
      if (this.hasSelection()) {
        Column() {
          Text('已选条件')
            .fontSize(18)
            .fontWeight(FontWeight.Bold)
            .margin({ top: 30, bottom: 10 })

          Row() {
            if (this.selectedCategory) {
              this.FilterTag(this.selectedCategory)
            }
            if (this.selectedSubCategory) {
              this.FilterTag(this.selectedSubCategory)
            }
          }
          .width('100%')
          .margin({ bottom: 8 })

          Row() {
            if (this.selectedBrand) {
              this.FilterTag(this.selectedBrand)
            }
            if (this.selectedPrice) {
              this.FilterTag(this.selectedPrice)
            }
          }
          .width('100%')
        }
        .width('100%')
        .padding(16)
        .backgroundColor('#F5F5F5')
        .borderRadius(8)
        .margin({ top: 20 })
      }

      // 确认按钮
      Button('确认筛选')
        .width('100%')
        .height(50)
        .backgroundColor('#007DFF')
        .borderRadius(8)
        .fontSize(18)
        .fontColor(Color.White)
        .margin({ top: 20 })
        .enabled(this.isFilterComplete())
        .opacity(this.isFilterComplete() ? 1 : 0.5)
        .onClick(() => {
          this.applyFilter()
        })
    }
    .width('100%')
    .height('100%')
    .padding(16)
  }

  @Builder
  SelectItem(label: string, value: string, options: string[], selectedIndex: number, onSelectCallback: (index: number) => void) {
    Row() {
      Text(label)
        .fontSize(16)
        .width(100)
      Select({
        value: value,
        selected: selectedIndex,
        options: options
      })
        .width('70%')
        .height(40)
        .backgroundColor(selectedIndex === -1 ? '#F5F5F5' : '#E6F2FF')
        .borderRadius(8)
        .fontColor(selectedIndex === -1 ? '#999999' : '#007DFF')
        .onSelect((index: number) => {
          onSelectCallback(index)
        })
    }
    .width('100%')
    .margin({ bottom: 20 })
  }

  @Builder
  FilterTag(text: string) {
    Text(text)
      .fontSize(14)
      .backgroundColor('#E6F2FF')
      .fontColor('#007DFF')
      .padding({ left: 12, right: 12, top: 6, bottom: 6 })
      .borderRadius(16)
      .margin({ right: 8 })
  }

  private resetSubSelections() {
    this.selectedSubCategory = ''
    this.selectedBrand = ''
    this.selectedPrice = ''
    this.subCategoryIndex = -1
    this.brandIndex = -1
    this.priceIndex = -1
    this.brands = []
  }

  private resetBrandAndPrice() {
    this.selectedBrand = ''
    this.selectedPrice = ''
    this.brandIndex = -1
    this.priceIndex = -1
  }

  private resetPrice() {
    this.selectedPrice = ''
    this.priceIndex = -1
  }

  private hasSelection(): boolean {
    return this.selectedCategory !== '' ||
      this.selectedSubCategory !== '' ||
      this.selectedBrand !== '' ||
      this.selectedPrice !== ''
  }

  private isFilterComplete(): boolean {
    return this.selectedCategory !== '' &&
      this.selectedSubCategory !== '' &&
      this.selectedBrand !== '' &&
      this.selectedPrice !== ''
  }

  private applyFilter() {
    const filterConditions = {
      category: this.selectedCategory,
      subCategory: this.selectedSubCategory,
      brand: this.selectedBrand,
      priceRange: this.selectedPrice
    }
    console.info('应用筛选条件:', JSON.stringify(filterConditions))
    // 处理筛选逻辑
  }
}

三、总结

本案例通过一个商品筛选器的示例,展示了 Select 组件的高级选择功能和自定义样式实现。通过配置 Select 组件的基本属性(如 value、selected、options 等),实现了标准的下拉选择功能。同时,通过自定义样式(如背景色、字体、圆角等),提升了下拉菜单的视觉效果。此外,通过事件监听(如 onSelect),实现了选项选中时的动态更新。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐