HarmonyOS 鸿蒙Next 自定义组件EasyPanel,bindsheet之外的选择,从底部弹出,可自定义顶部弧度

发布于 1周前 作者 htzhanglong 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 自定义组件EasyPanel,bindsheet之外的选择,从底部弹出,可自定义顶部弧度

组件定义部分的代码,使用时需要安装@pura/harmony-utils,也可以根据自己的情况选择组件或者自己实现获取屏幕高度部分的

import { DisplayUtil } from "[@pura](/user/pura)/harmony-utils"

export class EasyPanelController {
  private panel?: EasyPanel = undefined

  setPanel(panel: EasyPanel) {
    this.panel = panel
  }

  show() {
    this.panel?.show()
  }

  hide() {
    this.panel?.hide()
  }
}

@Component
export struct EasyPanel {
  @Link isShow: boolean
  @State translateY: number = 0
  @State opacityX: number = 0
  @State showContent: boolean = false
  private panelHeight: number = px2vp(DisplayUtil.getHeight() * 0.5)
  controller?: EasyPanelController

  aboutToAppear() {
    this.translateY = this.panelHeight
    if (this.controller) {
      this.controller.setPanel(this)
    }
  }

  show() {
    console.info('Panel show() called')
    this.showContent = true
    
    setTimeout(() => {
      animateTo({ 
        duration: 300, 
        curve: Curve.EaseOut 
      }, () => {
        this.translateY = 0
        this.opacityX = 0.5
      })
    }, 16)
  }

  hide() {
    animateTo({ 
      duration: 300, 
      curve: Curve.EaseOut,
      onFinish: () => {
        this.showContent = false
        this.isShow = false
      }
    }, () => {
      this.translateY = this.panelHeight
      this.opacityX = 0
    })
  }

  @Builder
  CloseButton() {
    Column(){
      Button({ type: ButtonType.Circle }) {
        Text('✕')
          .fontSize(16)
          .fontColor('#999999')
      }
      .width(32)
      .height(32)
      .backgroundColor('#dcdcdc')
      .onClick(() => this.hide())
    }.position({
      x: '90%',  // 距离右边 8%
      y: '12'    // 距离顶部 12px
    })
  }

  @Builder
  PanelContent() {
    Stack() {  // 使用 Stack 来实现绝对定位
      Column() {
        // 顶部拖动条
        Row() {
          Column()
            .width(40)
            .height(4)
            .backgroundColor('#dcdcdc')
            .borderRadius(2)
        }
        .width('100%')
        .height(20)
        .justifyContent(FlexAlign.Center)

        // 面板内容
        Column() {
          Text('Panel Content')
            .fontSize(20)
            .margin({ top: 20 })
        }
        .width('100%')
        .padding(20)
      }
      .width('100%')
      .height(this.panelHeight)
      .backgroundColor(Color.White)
      .borderRadius({ topLeft: 14, topRight: 14 })

      // 关闭按钮
      this.CloseButton()
    }
  }

  build() {
    if (this.isShow || this.showContent) {
      Stack() {
        // 遮罩层
        Column()
          .width('100%')
          .height('100%')
          .backgroundColor('#000000')
          .opacity(this.opacityX)
          .onClick(() => this.hide())
        
        if (this.showContent) {
          Column() {
            this.PanelContent()
          }
          .width('100%')
          .height('100%')
          .justifyContent(FlexAlign.End)  // 将面板放在底部
          .translate({ y: this.translateY })  // 控制面板的上下移动
          .animation({
            duration: 300,
            curve: Curve.EaseOut
          })
        }
      }
      .width('100%')
      .height('100%')
      .position({ x: 0, y: 0 })
      .zIndex(999)
    }
  }
}

页面使用EasyPanel

import { EasyPanel, EasyPanelController } from '../components/EasyPanel'

@Entry
@Component
struct Home {
  @State isShow: boolean = false
  controller: EasyPanelController = new EasyPanelController()

  build() {
    Stack() {
      Column() {
        Row() {
          Button("弹出panel")
            .width(200)
            .height(45)
            .onClick(() => {
              this.isShow = true
              this.controller.show()
            })
        }
        .width('100%')
        .justifyContent(FlexAlign.Center)
        .margin({ top: 100 })
      }

      EasyPanel({ 
        isShow: $isShow,
        controller: this.controller 
      })
    }
    .width('100%')
    .height('100%')
    .backgroundColor("#ffade2ad")
  }
}

如果大家发现有什么问题,欢迎留言交流


更多关于HarmonyOS 鸿蒙Next 自定义组件EasyPanel,bindsheet之外的选择,从底部弹出,可自定义顶部弧度的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

感谢楼主分享

更多关于HarmonyOS 鸿蒙Next 自定义组件EasyPanel,bindsheet之外的选择,从底部弹出,可自定义顶部弧度的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


针对帖子标题“HarmonyOS 鸿蒙Next 自定义组件EasyPanel,bindsheet之外的选择,从底部弹出,可自定义顶部弧度”的问题,以下是专业且直接的回答:

在HarmonyOS鸿蒙Next系统中,若要实现类似EasyPanel的自定义组件,且该组件具备从底部弹出、可自定顶部弧度的特性,同时作为bindsheet之外的选择,你需要利用鸿蒙系统的UI框架进行开发。

首先,你需要熟悉鸿蒙系统的ArkUI框架,这是开发鸿蒙应用界面的关键工具。通过ArkUI,你可以使用JavaScript或eTS(Enhanced TypeScript)语言来编写界面逻辑。

对于从底部弹出的效果,你可以使用鸿蒙系统的动画和布局系统来实现。具体来说,可以定义一个底部隐藏的面板,通过动画将其从底部滑动到屏幕中央或指定位置。

至于自定义顶部弧度的需求,你可以利用鸿蒙系统的自定义绘制功能。通过重写组件的绘制方法,你可以实现顶部弧度的自定义效果。这通常涉及到对Canvas对象的操作,如绘制圆弧、贝塞尔曲线等。

请注意,实现这些功能需要对鸿蒙系统的UI框架有深入的理解和实践经验。如果问题依旧没法解决,请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部