我爱她,可我如何面对之前的那个她——bindSheet半模态弹窗

 前言

        直到她猛然想起在《HarmonyOS》中所学的bindSheet半模态弹窗,她就是她,不能谈及是一个新的页面,但是依旧不能忽略,隐墨她转身,下定了某种决心.......


        一: bindSheet属性

        1.1 概念和作用

        bindSheet 是鸿蒙操作系统(HarmonyOS)中用于实现半模态页面的一个属性。它允许开发者将一个组件绑定为半模态页面,这种页面可以在不完全覆盖当前界面的情况下显示,通常用于弹出菜单、对话框等用户交互元素。半模态页面可以通过点击屏幕外部或特定的关闭按钮来关闭。

        1.2 参数

bindSheet(isShow: boolean, builder: CustomBuilder, options?: SheetOptions)
  • isShow (this.isWarning): 波尔类型,用于控制半模态页面是否显示。当 ishow 为 true 时,半模态页面显示;为false 时,半模态页面隐藏。

  • builder (this.WarningInformation()): 一个函数,返回Sheet的内容。构建半模态页面的内容,需要使用@Builder修饰

  • options: 一个对象,包含多个配置项来定制Sheet的外观和行为。包含半模态页面的可选配置。这些配置可以包括半模态页面的高度、背景颜色、模糊样式、是否显示关闭按钮等。

        1.3 options定制Sheet外观

        options 一个对象,包含多个配置项来定制Sheet的外观和行为

            detents: [700],
            backgroundColor: Color.White,
            blurStyle: BlurStyle.Thick,
            showClose: true,
            enableOutsideInteractive: false, //是否允许用户在 Sheet 以外的区域交互
            dragBar: true
  • detents: 一个数组,包含Sheet可能的高度或位置设置。在这个例子中,[700]表示Sheet的固定高度为700像素。

  • backgroundColor: 设置Sheet的背景颜色。这里使用Color.White来设置背景为白色。

  • blurStyle: 设置Sheet背后的模糊效果。BlurStyle.Thick表示使用较厚的模糊效果。

  • showClose: 布尔值,表示是否在Sheet中显示一个关闭按钮。true表示显示。

  • enableOutsideInteractive: 布尔值,表示Sheet显示时,用户是否可以与Sheet之外的区域进行交互。false表示禁止交互。

  • dragBar: 布尔值,表示Sheet是否有一个可拖动的条,用户可以通过拖动它来改变Sheet的显示位置或隐藏Sheet。true表示启用。


二: bindSheet示例

        本示例基于天气预报所构建的半模态弹窗,仅为展示 bindSheet 的实现效果。对于服务端获取数据 weatherMainInformation , daysWeather 和  airCondition。

        2.1 页面根组件处调用bindSheet

  @Prop weatherMainInformation: City<WeatherInformation>
  @Prop daysWeather: WeatherInformation
  @Prop airCondition: ConditionInformation

  @State isMainInformation:boolean = false
  @State isWarning :boolean = false

  build() {
    if (this.daysWeather.daily && this.airCondition.now != undefined) {
      Column({ space: 20 }) {
        Column({ space: 15 }) {
          Text(`${this.weatherMainInformation.detail?.now?.temp}°`).fontSize(120).fontWeight(600).fontColor(Color.White)
          Text(`${this.daysWeather.daily[0].tempMin}°/${this.daysWeather.daily[0].tempMax}°`)
            .fontSize(18)
            .fontWeight(500)
            .fontColor(Color.White)

          Row({ space: 20 }) {
            Text(`${this.weatherMainInformation.detail?.now?.text}`)
              .fontSize(21)
              .fontWeight(500)
              .fontColor(Color.White)
            Text(`空气${this.airCondition.now.category}`).fontSize(21).fontWeight(500).fontColor(Color.White)
          }
          .justifyContent(FlexAlign.Center)
        }
        .onClick(() => this.isMainInformation = !this.isMainInformation)
        .bindSheet(this.isMainInformation, this.MainInformation(), {
          detents: [700],
          backgroundColor: Color.White,
          blurStyle: BlurStyle.Thick,
          showClose: true,
          enableOutsideInteractive: false, //是否允许用户在 Sheet 以外的区域交互
          dragBar: true
        })


        if (this.airCondition.warning != undefined && this.airCondition.warning[0] != undefined) {
          Row({ space: 10 }) {
            Text(subString(this.airCondition.warning[0].title)).fontSize(18).fontWeight(400).fontColor(Color.White)
            Image($r('app.media.right_arrow')).width(30).fillColor(Color.White)
          }
          .onClick(() => this.isWarning = !this.isWarning)
          .bindSheet(this.isWarning, this.WarningInformation(), {
            detents: [700],
            backgroundColor: Color.White,
            blurStyle: BlurStyle.Thick,
            showClose: true,
            enableOutsideInteractive: false, //是否允许用户在 Sheet 以外的区域交互
            dragBar: true
          })
        }
      }
      .width('100%')
      .margin({
        left: 30,
        right: 30,
        top: 10,
        bottom: 10
      })
      .alignItems(HorizontalAlign.Center)
    }

        isMainInformation 和 isWarning 是定义的状态变量,它用于控制主信息区域的显示状态,通过点击改变 isMainInformation 和 isWarning 的值实现对于半模态弹窗的展示或者隐藏。对于不同的根组件有不同的展示效果。

   this.MainInformation() 和 this.WarningInformation() 为实现展开的内容。

        未展开的页面如下

        2.2 使用@Builder修饰组件

  //展开主要的天气信息
  @Builder MainInformation() {
    Column({ space: 10 }) {

      Column({ space: 5 }) {
        Text(this.weatherMainInformation.name).fontSize(20).fontWeight(CommonConstants.FONT_WEIGHT_600)
        if (this.weatherMainInformation.detail?.now?.obsTime) {
          Text(this.CalculateTime(this.weatherMainInformation.detail?.now?.obsTime)).fontSize(15).opacity(0.6)
        }
      }
      .width('100%')
      .height(50)
      .alignItems(HorizontalAlign.Start)


      if (this.weatherMainInformation.detail?.now && this.daysWeather.daily && this.airCondition.now != undefined) {
        Row() {
          Column({ space: 25 }) {
            Text(`${this.weatherMainInformation.detail?.now?.temp}°`)
              .fontSize(100)
              .fontWeight(500)

            Row() {
              Text(`${this.weatherMainInformation.detail?.now?.text} °`)
                .fontWeight(300)
                .fontSize(20).fontWeight(200)
              Text(`空气${this.airCondition.now.category}`).fontColor(Color.White).fontSize(10).fontWeight(300)
            }
            .justifyContent(FlexAlign.Center)
          }.layoutWeight(1)

          Image($r(`app.media.${this.weatherMainInformation.detail.now.icon}`)).width(100).height(100)
        }
        .justifyContent(FlexAlign.SpaceBetween)
        .width('100%')
        .margin(50)
      }

      Divider()
        .color('#ff5b5a5a')
        .width('95%')


      Grid() {
        if (this.weatherMainInformation.detail?.now) {
          GridItem() {
            this.RealTimeCard('体感温度', `${this.weatherMainInformation.detail?.now?.feelsLike}°`)
          }

          GridItem() {
            //风向
            this.RealTimeCard(this.weatherMainInformation.detail.now?.windDir,
              `${this.weatherMainInformation.detail?.now?.windScale}级`)
          }

          GridItem() {
            this.RealTimeCard('风向360角度', `${this.weatherMainInformation.detail?.now?.wind360}`)
          }

          GridItem() {
            this.RealTimeCard('相对湿度', `${this.weatherMainInformation.detail?.now?.humidity}%`)
          }

          GridItem() {
            this.RealTimeCard('过去1小时降水量', `${this.weatherMainInformation.detail?.now?.precip}/ml`)
          }

          GridItem() {
            this.RealTimeCard('大气压强', `${this.weatherMainInformation.detail?.now?.pressure}/BP`)
          }

          GridItem() {
            this.RealTimeCard('能见度', `${this.weatherMainInformation.detail?.now?.humidity}/Km`)
          }

          GridItem() {
            this.RealTimeCard('云量', `${this.weatherMainInformation.detail?.now?.cloud}%`)
          }

          GridItem() {
            this.RealTimeCard('露点温度', `${this.weatherMainInformation.detail?.now?.humidity}°`)
          }
        }
      }
      .width('100%')
      .height(300)
      .rowsTemplate('1fr 1fr 1fr')
      .columnsTemplate('1fr 1fr 1fr')
    }
    .width('95%')
    .height('100%')
    .margin({top:20})
    .padding(10)
  }



  //展开主要的预警信息
  @Builder WarningInformation(){

    Column({space:10}) {
      ForEach(this.airCondition.warning,(warn:getWarning)=>{
        List({space:15}) {
          ListItem() {
            Column({space:8}){
              Row({space:8}) {
                Image($r('app.media.warning_picture')).width(20).height(20)
                Text(warn.title).fontSize(16).fontWeight(500)
              }
              Text(formatDate(warn.pubTime)).fontSize(12).fontWeight(500)
              Text(warn.text).fontSize(16)
            }
            .alignItems(HorizontalAlign.Start)
            .padding(10)
            .margin(10)
            .width('95%')
          }
        }
        .width('100%')
      })
    }

  }



  @Builder RealTimeCard(title: string, context:string) {
    Column({ space: 8 }) {
      Text(title)
        .fontSize(12)
        .opacity(0.8)
      Text(context)
        .fontSize(16)
        .fontWeight(CommonConstants.FONT_WEIGHT_500)
    }
  }


  //计算时间的差值
  CalculateTime( data : string): string {
    // 移除时区偏移,将其转换为一个Date对象
    let obsDate = new Date(data.replace('T', ' ').replace('+08:00', ''));

    // 获取当前时间
    let currentDate = new Date();

    // 计算时间差,单位是毫秒, 将时间差转换为分钟
    let diffInMinutes = Math.floor((currentDate.getTime() - obsDate.getTime()) / (1000 * 60));

    // 根据时间差显示“X分钟前”
    let timeAgo:string = ''
    if (diffInMinutes < 1) {
      timeAgo = "刚刚发布";
    } else {
      timeAgo = diffInMinutes + "分钟前发布";
    }
    return timeAgo
  }

        对于点击不同的组件时会展现不同的 bindSheet 属性的内容

        this.MainInformation() 实现展开的内容。

        

         this.WarningInformation() 实现展开的内容。

         2.3 相关的注意事项

  • 确保在使用bindSheet时,相关的状态变量(如示例中的showSheet)是正确的,并且可以通过用户交互来更新。

  • 配置选项可以根据设计需求进行调整,以达到预期的用户界面效果

  • 在设计半模态页面时,考虑到用户体验,确保关闭按钮或外部点击可以关闭半模态页面,并且半模态页面的内容不会干扰用户对主界面的操作


        后言

        “当着天空中出现乌云的时候,我们就指出:这不过是暂时的现象,黑暗即将过去,曙光即在前头。”

        任何状态都是一时的,不是永久的。昨天在哭今天在笑,昨天今天失败明天成功了,去年钱多多今年大破产。无常是常态。得到的总会失去,又有新的得到。你会困难,你会绝望,但当你咬牙坚持下去时,你看过去的日子,让你真正寻味的是自己的态度,对自己生活的态度!

        前进吧,少年!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值