鸿蒙带你实现丝滑的弹框

253 阅读4分钟

鸿蒙带你实现丝滑的弹框

一、模态框应用场景。

在生活当中,我们无时无刻不在接触着拥有弹窗效果的APP,在使用的过程中,我们发现它的存在,给我们带来了很大的便利,比如:

  1. 我们在选择地址的时候需要用户进行多步操作或选择时,通过全模态转场弹出一个新的简洁的页面,来让用户便捷的进行选择地址的操作。
  2. 用户需要分享或显示菜单的时候。

效果图

image.png

image.png

二、模态转场的特点。

模态转场是一种在用户界面设计中常用的动画效果,特点是在旧的界面上覆盖一个新的页面,给用户流畅的体验,使页面切换更加自然和流畅。

  1. 不消失性:新的界面直接覆盖在旧的界面上,不会使旧的页面消失。
  2. 动画效果:通过添加过渡动画、如渐变、滑动、缩放等,使新界面出现和旧界面的隐藏更加平滑和吸引人。

三、实现(全/半)模态转场的思路与技术。

1.实现思路

  1. 定义模态展示界面:使用适合的布局和组件构建页面,要确保内容清晰和布局合理。
  2. 设置转场动画:通过给新界面添加新旧界面的隐藏和出现添加过渡效果,实现丝滑的转场,如平移、缩放、淡入淡出。
  3. 控制显示和隐藏:通过状态变量控制模态界面的显示和隐藏,以及在适当的时机和位置触发转场动画。

2.使用的技术

在鸿蒙开发中,半模态转场通过bindSheet属性实现、全模态转场通过bindContentCover属性实现,两者转场是类似的,都需要开发者定义一个控制变量来控制全/半模态对话框的显示和隐藏,并通过bindSheet/bindContentCover将控制变量与模态对话框的内容进行绑定。此外,bindSheet/bindContentCover还允许开发者自定义转场动画、背景色等属性,以提供更加丰富的用户体验。

3.语法及参数的使用

语法

@Entry
  @Component
  struct SheetTransitionExample1 {
    // 1. 定义控制变量
    @State isShow: boolean = false

    // 2.自定义内容
    @Builder
    myBuilder() {
       // 结构略
    }

    build() {
      Column() {
        Button(`显示半/全模态`)
          //  3.绑定半模态框
          .bindSheet(this.isShow, this.myBuilder())  //半模态框绑定,这里需要传入两个参数,一个是控制变量,一个是自定义内容
          //.bindContentCover(this.isShow, this.myBuilder())  //全模态框绑定,这里需要传入两个参数,一个是控制变量,一个是自定义内容
          .onClick(() => {
            // 4.控制显示
            this.isShow = true
          })
      }
    }
  }

参数

参数参数描述
isShow是否显示半模态页面。
builder:配置半模态页面内容。
options?:配置半模态页面的可选属性。

可选属性sheetOptions

名称类型必填描述
heightSheetSize、Length半模态高度,默认是LARGE。说明:底部弹窗竖屏时,当设置detents时,该属性设置无效。
dragBarboolean是否显示控制条,默认显示。说明:半模态面板的dentents属性设置多个不同高度并且设置生效时,默认显示控制条。否则不显示控制条。
showCloseboolean 、 Resource是否显示关闭图标,默认显示。
detents半模态页面的切换高度档位。**说明:**底部弹窗竖屏生效,元组中第一个高度为初始高度。

4.注意

在非双向绑定情况下,以拖拽方式关闭半模态页面不会改变isShow参数的值。 为了使isShow参数值与半模态界面的状态同步,建议使用 $$ (建议最后加)双向绑定isShow参数。

5.实现效果图及代码(分享给好友)

image.png

代码

/*
 * 需求:
 * 1. 点击按钮 弹出半模态
 *      定义状态变量
 *      bindSheet($$this.状态变量,自定义的 Builder,{})
 * */
@Entry
@Component
struct SheetTransitionExample1 {
  @State isShow:boolean = false

  // 半模态 Builder
  @Builder
  myBuilder() {
    Column() {
      Stack({ alignContent: Alignment.End }) {
        Text('分享给好友')
          .width('100%')
          .textAlign(TextAlign.Center)
          .fontSize(20)
        // 自己的关闭按钮-因为没用默认的,需要自己实现关闭逻辑
        Image($r('app.media.ic_public_cancel'))
          .width(25)
          .fillColor('#c0c0c0')
          .onClick(()=>{
            this.isShow=false
          })
      }
      .width('100%')

      Row() {
        this.itemBuilder($r('app.media.ic_share_sina'), '微信')
        this.itemBuilder($r('app.media.ic_share_url'), '朋友圈')
        this.itemBuilder($r('app.media.ic_share_wechat'), '微博')
        this.itemBuilder($r('app.media.ic_share_pyq'), '复制链接')
      }
      .height(80)
      .width('100%')
      .margin({ top: 30 })
      .justifyContent(FlexAlign.SpaceAround)
    }
    .padding(15)
  }

  // 半模态 内部图片 Builder
  @Builder
  itemBuilder(src: ResourceStr, title: string) {
    Column() {
      Image(src)
        .width(50)
      Text(title)
        .fontSize(14)
        .margin({ top: 10 })
    }
  }

  build() {
    Column() {
      Button(`显示半模态`)
        .fontSize(20)
        .bindSheet($$this.isShow,this.myBuilder(),{
          height:SheetSize.FIT_CONTENT,
          showClose:false // 默认的关闭按钮 有背景,不太好看 关掉
        })
        .onClick(()=>{
          this.isShow=true
        })

      // 展示半模态Builder
      // this.myBuilder()

    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
  }
}

注意:

  1. 半模态中的图片如果不设置高度,默认不会加载,导致半模态默认不显示图片
  2. 解决方法:给图片或图片的容器加个高度即可