diff --git a/build-profile.json5 b/build-profile.json5 index a352b70..7d23ab9 100644 --- a/build-profile.json5 +++ b/build-profile.json5 @@ -1,22 +1,36 @@ { "app": { - "signingConfigs": [], "products": [ { "name": "default", "signingConfig": "default", "compileSdkVersion": "4.0.0(10)", "compatibleSdkVersion": "4.0.0(10)", - "runtimeOS": "HarmonyOS", + "runtimeOS": "HarmonyOS" } ], "buildModeSet": [ { - "name": "debug", + "name": "debug" }, { "name": "release" } + ], + "signingConfigs": [ + { + "name": "default", + "type": "HarmonyOS", + "material": { + "certpath": "C:\\Users\\Administrator\\.ohos\\config\\auto_debug_harmony_demo_panel_com.example.myapplication_70086000144137060.cer", + "storePassword": "0000001B767E7E8C6D3EBFB6061DAE0E0136D0BDF27E3115977950BFFF98B3355E9353160B972AA3C07C07", + "keyAlias": "debugKey", + "keyPassword": "0000001BBD05595914755974A2674C85F88396B4366BFBEE8893724421C4C36C138D1BC83330092A159397", + "profile": "C:\\Users\\Administrator\\.ohos\\config\\auto_debug_harmony_demo_panel_com.example.myapplication_70086000144137060.p7b", + "signAlg": "SHA256withECDSA", + "storeFile": "C:\\Users\\Administrator\\.ohos\\config\\auto_debug_harmony_demo_panel_com.example.myapplication_70086000144137060.p12" + } + } ] }, "modules": [ diff --git a/entry/oh-package.json5 b/entry/oh-package.json5 index 248c3b7..225946c 100644 --- a/entry/oh-package.json5 +++ b/entry/oh-package.json5 @@ -1,10 +1,10 @@ { + "license": "", + "devDependencies": {}, + "author": "", "name": "entry", - "version": "1.0.0", "description": "Please describe the basic information.", "main": "", - "author": "", - "license": "", + "version": "1.0.0", "dependencies": {} } - diff --git a/entry/src/main/ets/components/CustomPanel.ets b/entry/src/main/ets/components/CustomPanel.ets new file mode 100644 index 0000000..ee94be5 --- /dev/null +++ b/entry/src/main/ets/components/CustomPanel.ets @@ -0,0 +1,51 @@ +/** + * 定制可上下滑动的panel + * + * @param show: 控制面板显示 + * @param contentView: 面板内部显示的组件 + * @param defaultHeight: 默认高度,取值范围为[0, 1000] + * @param showDragBar: 是否显示顶部bar + * @param onClose: 关闭时的回调函数,可选 + * @author cheliangzhao + */ +@Component +export struct CustomPanel { + private TAG: string = 'CustomPanel' + @Link show: boolean + @BuilderParam contentView: () => void + @Prop defaultHeight: number = 800 + @Prop showDragBar: boolean = false; + onClose?: () => void + + aboutToAppear() { + console.info(this.TAG, 'aboutToAppear') + } + + closePanel() { + this.show = false; + if (this.onClose) this.onClose(); + } + + @Builder + innerView() { + this.contentView() + } + + build() { + Panel(this.show) { + this.innerView(); + } + .type(PanelType.Foldable) + .mode(PanelMode.Half) + .dragBar(this.showDragBar) // 默认关闭 + .halfHeight(this.defaultHeight) // 默认一半 + .backgroundMask('#B3111317') // mask color + .position({ x: 0, y: 0 }) + .padding({ top: 30 }) // TODO: 根据状态栏高度设置 + .onChange((width: number, height: number, mode: PanelMode) => { + if (mode == 0) { + this.closePanel() // 下滑关闭 + } + }) + } +} diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 89bf1e7..ecaecf9 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -1,17 +1,122 @@ +// 下滑弹窗测试 +import { CustomPanel } from '../components/CustomPanel'; +import curves from '@ohos.curves'; +import { InnerView } from '../views/InnerView' + +// 方案1:panel +// 方案2:模态转场 @Preview @Entry @Component struct Index { + private TAG: string = 'Index' + private defaultWidth: number = 350 @State message: string = "This a Template Project" + @State showPanel: boolean = false; + // 模态转场控制变量 + @State isPresent: boolean = false; + @State contentWidth: number | string = this.defaultWidth; + @State marginLeft: number = 0; + + @Builder + innerView() { + InnerView(); + } + + handleClose() { + this.isPresent = false; + } + + // sidebar控制变量 + controlValue = { + beginX: 0, + endX: 0, + maxMoveRate: 0.12, + swipeDirection: 0, // 0 is left, 1 is right + leftMoveDistance: 0, + } + + @Builder + SideBar() { + InnerView() + .margin({ left: -this.marginLeft }) + .width(this.contentWidth) + .height('100%') + .transition(// 通过转场动画实现出现消失转场动画效果,transition需要加在builder下的第一个组件 + TransitionEffect.translate({ x: '-' + this.contentWidth, y: 0, z: 0 }) + .animation({ curve: curves.springMotion(0.6, 0.8) }) + ) + .onTouch(event => { + // 按下赋初始值 + if (event.type === TouchType.Down) { + this.controlValue.beginX = event.touches[0].displayX; + this.controlValue.leftMoveDistance = 0; + } + // 移动改变移动宽度 + if (event.type === TouchType.Move) { + this.controlValue.endX = event.touches[0].displayX; // 手指停止的位置 + const moveDistance = this.controlValue.beginX - this.controlValue.endX; // 滑动的水平距离 + + // 判断水平滑动方向 + if (this.controlValue.leftMoveDistance > 0) { + this.controlValue.swipeDirection = 0; + } else { + this.controlValue.swipeDirection = 1; + } + + // 更新 + this.marginLeft = (this.marginLeft + moveDistance) > 0 ? (this.marginLeft + moveDistance) : 0; + + this.controlValue.beginX = this.controlValue.endX; + + this.controlValue.leftMoveDistance += moveDistance + } + + if (event.type === TouchType.Up) { + console.log(this.TAG, 'TouchType up' + this.controlValue.leftMoveDistance); + if (this.controlValue.leftMoveDistance > this.controlValue.maxMoveRate * +this.defaultWidth) { + this.isPresent = false; + } + this.marginLeft = 0; + } + }) + .gesture( + SwipeGesture({ direction: SwipeDirection.Horizontal }) + .onAction((event?: GestureEvent) => { + if (event && this.controlValue.swipeDirection == 0) { + this.isPresent = false; + this.marginLeft = 0; + } + }) + ) // 快速滑动关闭 + } build() { Row() { - Text(this.message) - .fontSize(40) - .fontWeight(FontWeight.Bold) + Button('open panel') + .onClick(() => this.showPanel = true); + Button('模态转场')// 通过选定的模态接口,绑定模态展示界面,ModalTransition是内置的ContentCover转场动画类型,这里选择None代表系统不加默认动画 + .bindContentCover(this.isPresent, this.SideBar, ModalTransition.NONE) + .onClick(() => { + if (this.isPresent) { + this.isPresent = false; + this.isPresent = true; + } else { + this.isPresent = true; + } + this.contentWidth = this.defaultWidth; + }) + + CustomPanel({ + contentView: () => this.innerView(), + show: this.showPanel, + defaultHeight: 500, + showDragBar: true + }); } - .height('100%') .width('100%') - .justifyContent(FlexAlign.Center) + .height('100%') + .justifyContent(FlexAlign.SpaceEvenly) + } -} \ No newline at end of file +} diff --git a/entry/src/main/ets/views/InnerView.ets b/entry/src/main/ets/views/InnerView.ets new file mode 100644 index 0000000..5e27511 --- /dev/null +++ b/entry/src/main/ets/views/InnerView.ets @@ -0,0 +1,29 @@ +// TODO: 请扫点距离返回动画 +@Preview +@Component +export struct InnerView { + @State message: string = "This is a Inner View"; + + build() { + Column() { + Text(this.message) + .margin({ top: 10, bottom: 10 }) + Scroll() { + Column() { + ForEach(Array.from({ length: 20 }).map((_, idx) => idx + 1), item => { + Text(`item: ${item}`) + .width('100%') + .backgroundColor('#FFFFFF') + .height(60) + .margin({ bottom: 10 }) + .borderRadius(8) + .padding({ left: 16, right: 16 }) + }) + } + .width('100%') + .padding({ left: 16, right: 16 }) + } + } + .backgroundColor('#E6E8EC') + } +} diff --git a/oh-package.json5 b/oh-package.json5 index 080ede4..16d0070 100644 --- a/oh-package.json5 +++ b/oh-package.json5 @@ -1,13 +1,12 @@ { - "name": "template-responsive", - "version": "1.0.0", - "description": "Please describe the basic information.", - "main": "", - "author": "", "license": "", - "dependencies": { - }, "devDependencies": { "@ohos/hypium": "1.0.6" - } + }, + "author": "", + "name": "template-responsive", + "description": "Please describe the basic information.", + "main": "", + "version": "1.0.0", + "dependencies": {} }