feat: finish sidebar
This commit is contained in:
parent
264c7a7dbc
commit
914c1ca917
|
@ -1,22 +1,36 @@
|
||||||
{
|
{
|
||||||
"app": {
|
"app": {
|
||||||
"signingConfigs": [],
|
|
||||||
"products": [
|
"products": [
|
||||||
{
|
{
|
||||||
"name": "default",
|
"name": "default",
|
||||||
"signingConfig": "default",
|
"signingConfig": "default",
|
||||||
"compileSdkVersion": "4.0.0(10)",
|
"compileSdkVersion": "4.0.0(10)",
|
||||||
"compatibleSdkVersion": "4.0.0(10)",
|
"compatibleSdkVersion": "4.0.0(10)",
|
||||||
"runtimeOS": "HarmonyOS",
|
"runtimeOS": "HarmonyOS"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"buildModeSet": [
|
"buildModeSet": [
|
||||||
{
|
{
|
||||||
"name": "debug",
|
"name": "debug"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "release"
|
"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": [
|
"modules": [
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{
|
{
|
||||||
|
"license": "",
|
||||||
|
"devDependencies": {},
|
||||||
|
"author": "",
|
||||||
"name": "entry",
|
"name": "entry",
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "Please describe the basic information.",
|
"description": "Please describe the basic information.",
|
||||||
"main": "",
|
"main": "",
|
||||||
"author": "",
|
"version": "1.0.0",
|
||||||
"license": "",
|
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
51
entry/src/main/ets/components/CustomPanel.ets
Normal file
51
entry/src/main/ets/components/CustomPanel.ets
Normal file
|
@ -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() // 下滑关闭
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +1,122 @@
|
||||||
|
// 下滑弹窗测试
|
||||||
|
import { CustomPanel } from '../components/CustomPanel';
|
||||||
|
import curves from '@ohos.curves';
|
||||||
|
import { InnerView } from '../views/InnerView'
|
||||||
|
|
||||||
|
// 方案1:panel
|
||||||
|
// 方案2:模态转场
|
||||||
@Preview
|
@Preview
|
||||||
@Entry
|
@Entry
|
||||||
@Component
|
@Component
|
||||||
struct Index {
|
struct Index {
|
||||||
|
private TAG: string = 'Index'
|
||||||
|
private defaultWidth: number = 350
|
||||||
@State message: string = "This a Template Project"
|
@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() {
|
build() {
|
||||||
Row() {
|
Row() {
|
||||||
Text(this.message)
|
Button('open panel')
|
||||||
.fontSize(40)
|
.onClick(() => this.showPanel = true);
|
||||||
.fontWeight(FontWeight.Bold)
|
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%')
|
.width('100%')
|
||||||
.justifyContent(FlexAlign.Center)
|
.height('100%')
|
||||||
|
.justifyContent(FlexAlign.SpaceEvenly)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
29
entry/src/main/ets/views/InnerView.ets
Normal file
29
entry/src/main/ets/views/InnerView.ets
Normal file
|
@ -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')
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "template-responsive",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "Please describe the basic information.",
|
|
||||||
"main": "",
|
|
||||||
"author": "",
|
|
||||||
"license": "",
|
"license": "",
|
||||||
"dependencies": {
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ohos/hypium": "1.0.6"
|
"@ohos/hypium": "1.0.6"
|
||||||
}
|
},
|
||||||
|
"author": "",
|
||||||
|
"name": "template-responsive",
|
||||||
|
"description": "Please describe the basic information.",
|
||||||
|
"main": "",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"dependencies": {}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user