HarmonyOS ArkUi 低侵入实现根据点击位置弹出筛选框

效果图

本项目业务是几个下拉框数据是一个接口,需要根据选择的数据,实时刷新其他下拉框数据

在这里插入图片描述

实现方式

有4种实现方式:

  1. bindPopup
  2. 在对应的界面上盖一层组件
  3. promptAction.openCustomDialog
  4. CustomDialog:自定义弹窗

第1、2种方式都已一个共同的缺陷:如果下拉筛选框在主界面的情况(底部几个tab ,点击tab 切换界面),每个界面的顶部有下拉筛选框的情况下,下拉筛选框会遮挡不住底部的tab。

第3种方式:弹窗把状态栏无法覆盖(暂时没找到相关属性,后面找到会补充),但是也能满足现在下拉框的需求,如果是全屏覆盖显示的话 ,需要慎重考虑。
注意:第3种方式,设置 offset 偏移量 ,需要减去状态栏的高度

第3、4两种方式其实写法上差不多的。
最后还是选择第4种方式

第4种:CustomDialog实现方式

Dialog

import { RadioBean } from '../../bean/FilBean'

interface RadioInterface {
  onClick?: (radioBean: RadioBean) => void
}

@Preview
@CustomDialog
export struct RadioDialog {
  controller: CustomDialogController
  @Prop list: RadioBean[]
  click?: RadioInterface
  // 单向监听:记录最后一次的选择
  @Prop lastSelect: string
  // 用于区分默认状态的文字,可根据此值设置字体颜色
  @Prop defaultSelect: string

  aboutToAppear() {
  }

  build() {
    Column() {
      Column() {
        if (this.list) {
          List() {
            ForEach(this.list, (item: RadioBean) => {
              ListItem() {
                Row() {
                  if (this.lastSelect) {
                    if (this.lastSelect == item.desc) {
                      Text(item.desc).height('100%').fontSize(12).fontColor('#007FFF')
                      Image($r('app.media.icon_select_blue')).width(15).height(15)
                    } else {
                      Text(item.desc).height('100%').fontSize(12).fontColor('#303242')
                    }
                  } else {
                    if (item.desc == this.defaultSelect) {
                      Text(item.desc).height('100%').fontSize(12).fontColor('#007FFF')
                      Image($r('app.media.icon_select_blue')).width(15).height(15)
                    } else {
                      Text(item.desc).height('100%').fontSize(12).fontColor('#303242')
                    }
                  }
                }.padding({ left: 15, right: 15 }).height(50).justifyContent(FlexAlign.SpaceBetween).width('100%')
              }.onClick(() => {
                if (this.click) {
                  this.click?.onClick!(item)
                }
              })
            })
          }
          .constraintSize({ maxHeight: 400, minHeight: 0 })
          .backgroundColor(Color.White)
        }
      }
      .height('100%')
      .backgroundColor("#90000000")
      .onClick(() => {
        this.controller.close()
      })
    }.height('100%').backgroundColor(Color.Transparent)
  }
}

使用

注意

  1. 自定义弹窗如果封装到一个方法里,如下面代码showYearDialog所示,自定义弹窗RadioDialog内,无法使用**@Link双向绑定**,会报错
Error message:is not callable
  1. 不放在单独方法里,@Link双向绑定,是可以正常使用的

  showYearDialog() {
    this.controller = new CustomDialogController({
      builder: RadioDialog({
        lastSelect: this.year,
        defaultSelect: '全部年份',
        list: this.filBean.yearList,
        click: {
          onClick: (item) => {
          //点击选项后 处理自己的交互效果
            if (item.desc) {
              if (item.desc == '全部年份') {
                this.year = ''
              } else {
                this.year = item.desc
              }
              this.tabArr[2] = item.desc
              this.pageIndex = 1
              this.reqSearch()
            }
            this.controller?.close()
          }
        }
      }),
      cancel: () => {
        this.controller?.close()
      },
      // 设置全屏弹窗,利用offset设置偏移量
      // this.postionY(刚好贴着组件下方弹窗) = 当前组件的高度 + 组件顶部在屏幕中距离顶部的距离
      offset: { dx: 0, dy: this.postionY },
      autoCancel: true,
      customStyle: true,
      maskColor: Color.Transparent,
      openAnimation: { duration: 0 },
      closeAnimation: { duration: 0 }
    });
    this.controller.open()
  }

this.postionY

点击组件可根据 ClickEvent 获取具体组件在屏幕中的位置
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值