问题现象
在使用bindSheet时,只能显示一个弹窗内容,如何在bindSheet中实现页面切换的效果?
背景知识
bindSheet:半模态页面(bindSheet)默认是模态形式的非全屏弹窗式交互页面,允许部分底层父视图可见,帮助用户在与半模态交互时保留其父视图环境。半模态页面适用于展示简单的任务或信息面板,例如,个人信息、文本简介、分享面板、创建日程、添加内容等。若需展示可能影响父视图的半模态页面,半模态支持配置为非模态交互形式。
onAreaChange:组件区域变化时触发该回调。仅会响应由布局变化所导致的组件大小、位置发生变化时的回调。
animateTo:提供animateTo接口来指定由于闭包代码导致的状态变化插入过渡动效。
translate:设置页面转场时的平移效果。
解决方案
实现思路如下:
半模态页面实现:使用Stack容器层叠布局两个组件,通过@State变量动态控制组件显隐状态,从而实现组件切换。
动画效果优化:为组件绑定onClick点击事件,使用animateTo设置动画持续时间,再指定由于闭包代码导致的状态变化插入过渡动效。
.onClick(() => {
this.title = '子集标题';
this.getUIContext()?.animateTo({
duration: 800, // 动画持续时间,单位为毫秒。
curve: Curve.EaseOut, // 动画曲线。
playMode: PlayMode.Normal, // 动画播放模式,默认播放完成后重头开始播放。 默认值:PlayMode.Normal
onFinish: () => {
console.info('play end');
}
}, () => {
// 指定显示动效的闭包函数,在闭包函数中导致的状态变化系统会自动插入过渡动画。
this.flag = !this.flag;
});
});
页面切换实现:translate属性实现页面切换效果,平移距离通过onAreaChange回调动态获取弹窗宽度,避免不同设备动画的移动尺寸不同。
SheetBuilder2({ title: this.title, flag: this.flag })
.width('100%')
.height('100%')
.translate(this.flag ? { x: 0 } : { x: this.translateX })
.onAreaChange((oldValue: Area, newValue: Area) => {
console.info('testTag', 获取到oldValue、newValue:${oldValue.width}、${newValue.width});
// 适配其他尺寸设备时,使用onAreaChange获取宽度,动画的移动尺寸直接取弹窗的宽度。
this.translateX = newValue.width as number;
});
完整代码如下:
@Entry
@Component
struct SheetDemo {
@State isShowSheet: boolean = false;
private items: number[] = [0, 1, 2, 3, 4];
@State title: string = '标题';
@State flag: boolean = false;
@State translateX: number = 0;
@Builder
SheetBuilder() {
Stack() {
Column() {
Row() {
Text(this.title);
}
.padding({ left: 20, right: 20 })
.height('50')
.width('100%');
List({ space: '10vp' }) {
ForEach(this.items, (item: number) => {
ListItem() {
Text(String(item)).fontSize(16).fontWeight(FontWeight.Bold);
}
.width('90%')
.height('80vp')
.backgroundColor('#E5E5E5')
.borderRadius(10)
.onClick(() => {
this.title = '子集标题';
this.getUIContext()?.animateTo({
duration: 800, // 动画持续时间,单位为毫秒。
curve: Curve.EaseOut, // 动画曲线。
playMode: PlayMode.Normal, // 动画播放模式,默认播放完成后重头开始播放。 默认值:PlayMode.Normal
onFinish: () => {
console.info('play end');
}
}, () => {
// 指定显示动效的闭包函数,在闭包函数中导致的状态变化系统会自动插入过渡动画。
this.flag = !this.flag;
});
});
});
}
.alignListItem(ListItemAlign.Center)
.margin({ top: '10vp' })
.width('100%')
.height('100%');
}.width('100%').height('100%')
.translate(this.flag ? { x: -this.translateX } : { x: 0 });
SheetBuilder2({ title: this.title, flag: this.flag })
.width('100%')
.height('100%')
.translate(this.flag ? { x: 0 } : { x: this.translateX })
.onAreaChange((oldValue: Area, newValue: Area) => {
console.info('testTag', `获取到oldValue、newValue:${oldValue.width}、${newValue.width}`);
// 适配其他尺寸设备时,使用onAreaChange获取宽度,动画的移动尺寸直接取弹窗的宽度。
this.translateX = newValue.width as number;
});
};
}
build() {
Column() {
Button('Open Sheet').width('90%')
.onClick(() => {
this.isShowSheet = !this.isShowSheet;
})
.bindSheet($$this.isShowSheet, this.SheetBuilder(), {
detents: [SheetSize.MEDIUM, SheetSize.LARGE, 600],
preferType: SheetType.BOTTOM,
});
}.width('100%').height('100%')
.justifyContent(FlexAlign.Center);
}
}
@Component
struct SheetBuilder2 {
@Link title: string;
@Link flag: boolean;
build() {
Column() {
Row() {
Column() {
Image($r('sys.media.ohos_ic_compnent_titlebar_back'))
.height(24)
.width(24)
.fillColor('#313232');
}
.borderRadius(40)
.width(40)
.height(40)
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
.backgroundColor('#e6e8e9')
.margin({ right: 8 })
.onClick(() => {
this.title = '标题';
this.getUIContext()?.animateTo({
duration: 500,
curve: Curve.EaseOut,
playMode: PlayMode.Normal,
onFinish: () => {
console.info('play end');
}
}, () => {
this.flag = !this.flag;
});
});
Text(this.title);
}
.height('50')
.width('100%');
Column() {
Text('子集页面');
}
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
.width('100%')
.layoutWeight(1);
}.width('100%').height('100%').padding({ right: 18, left: 18 });
}
}
效果图如下:
点击放大
总结
适用于弹窗内页面切换效果场景。
https://pastebin.com/MkikWYWz
https://pastebin.com/9Bfjbb0M
https://pastebin.com/mVVctW8C
https://pastebin.com/CZf6kYsb
https://pastebin.com/43JVAwVA
https://pastebin.com/RennQGtK
https://pastebin.com/fLVTxmpf
https://pastebin.com/UnRGvVsy
https://pastebin.com/SJfdsLEP
https://pastebin.com/eRyfC1Mb
https://pastebin.com/p14mXacT
https://pastebin.com/1Mtt4F5V
https://pastebin.com/7Ha3G1PM
https://pastebin.com/XiTqnLfU
https://pastebin.com/pGMNvVFY
https://pastebin.com/pwjMAnPd
https://pastebin.com/h03MMmgC
https://pastebin.com/86PB1gQb
https://pastebin.com/UnjxznuU
https://pastebin.com/xcQiSJxM
https://pastebin.com/Rhb1K8AZ
https://pastebin.com/a0XN9y8y
https://pastebin.com/cu6MJzfs
https://pastebin.com/iKBAW9Pv
https://pastebin.com/pue02cdc
https://pastebin.com/7UZ2hR3G
https://pastebin.com/f9meVaDT
https://pastebin.com/ddiWiaBQ
https://pastebin.com/rs4mrKbA
https://pastebin.com/gYjd85MD
https://pastebin.com/uBp9K0cU
https://pastebin.com/mQRm3pzp
https://pastebin.com/qpsiXmCU
https://pastebin.com/rjM0i1Lt
https://pastebin.com/qTBnebTj
https://pastebin.com/fJDMGuHe
https://pastebin.com/aQPkvbqQ
https://pastebin.com/mgXUpdXh
https://pastebin.com/m5r4JEWd
https://pastebin.com/Wej9f9gK
https://pastebin.com/NBKatceE
https://pastebin.com/GvNjMx2z
https://pastebin.com/fsnAGNXc
https://pastebin.com/kc0WPrkW
https://pastebin.com/UEzuEiSC
https://pastebin.com/4dA4beCZ
https://pastebin.com/iDdpTAN6
https://pastebin.com/WDiXDXyZ
https://pastebin.com/b05n3wrc
https://pastebin.com/r66uFEcA
https://pastebin.com/sChfMSeh
https://pastebin.com/L8vZb5h6
https://pastebin.com/SXBFxdLY
https://pastebin.com/Q45Nz7pN
https://pastebin.com/rXQEiQ8g
https://pastebin.com/DCdKPuBx
https://pastebin.com/vb7DiZJ5
https://pastebin.com/AM1Viyzk
https://pastebin.com/LTLrwCut
https://pastebin.com/LESuyLw6
https://pastebin.com/DV36bTiK
https://pastebin.com/7pui77mG
https://pastebin.com/dipWeEn1
https://pastebin.com/fDDC3UpV
https://pastebin.com/dntFDftN
https://pastebin.com/0NvZwgaC
https://pastebin.com/zAxXntwm
https://pastebin.com/qJ0wuWXe
https://pastebin.com/CFMSE99J
https://pastebin.com/NrjAD2gJ
https://pastebin.com/WEQ7kU6f
https://pastebin.com/r9Hz7Pyr
https://pastebin.com/m6X7dtYF
https://pastebin.com/6GZYPF1W
https://pastebin.com/hC6aZxiH
https://pastebin.com/GyG08gUp
https://pastebin.com/rk5WWN9J
https://pastebin.com/TJgCHUQK
https://pastebin.com/ymYitWqH
https://pastebin.com/Jv4XgCg3
https://pastebin.com/msCWSjGe
https://pastebin.com/qKZ1Snsk
https://pastebin.com/Jj2vhKbL
https://pastebin.com/XXEQWsMc
https://pastebin.com/g9y2wTeq
https://pastebin.com/DmQZVPjt
https://pastebin.com/UXSMvzxX
https://pastebin.com/4a49bzVg
https://pastebin.com/HEGtnaGP
https://pastebin.com/Y36ybY24
https://pastebin.com/4n2YcsUC
https://pastebin.com/ZpYc7t61
https://pastebin.com/y3eQM94N
https://pastebin.com/DUVEPyzM
https://pastebin.com/VtMN3MjF
https://pastebin.com/2RtvFwwg
https://pastebin.com/1Nd2wugV
https://pastebin.com/iTRp54Ru
https://pastebin.com/uTgc26BY
https://pastebin.com/0vv8J51p
https://pastebin.com/5dJQUQc8
https://pastebin.com/Vwa4hYKM
https://pastebin.com/VtGik99k
https://pastebin.com/xnJpLS1J
https://pastebin.com/YD7k957h
https://pastebin.com/yYDTbZtf
https://pastebin.com/4NdTjX9R
https://pastebin.com/0z5W1JZ9
https://pastebin.com/7Ziq14S2
https://pastebin.com/qMA2iDK1
https://pastebin.com/MHJ9K8h9
https://pastebin.com/YSDx1MdQ
https://pastebin.com/kCQ6d6SH
https://pastebin.com/aG2AT3uR
https://pastebin.com/enZHN9sT
https://pastebin.com/WneHgr97
https://pastebin.com/1awKkxjq
https://pastebin.com/eA5c4wa1
https://pastebin.com/cw8LSnL6
https://pastebin.com/mxBX1K3t
https://pastebin.com/s74nExv3
https://pastebin.com/7jdDbnV3
https://pastebin.com/jNxEhVzd
https://pastebin.com/BsSQ53mF
https://pastebin.com/zWZDRtrK
https://pastebin.com/xWgwUQQk
https://pastebin.com/AAxLbWYu
https://pastebin.com/96NLWa8v
https://pastebin.com/na7WvpHw
https://pastebin.com/zVvAL7YN
https://pastebin.com/tRQdAsDJ
https://pastebin.com/pDGyYZ6x
https://pastebin.com/dJFmK6w1
https://pastebin.com/AyuXrhzJ
https://pastebin.com/6Dq5Zeic
https://pastebin.com/GfJbgMka
https://pastebin.com/q9JE5urV
https://pastebin.com/HXcU9WZn
https://pastebin.com/xN3wm2fa
https://pastebin.com/n2YzdzDX
https://pastebin.com/xjXaBXJp
https://pastebin.com/kvELGMZP
https://pastebin.com/qtZkQvUC
https://pastebin.com/Vn1ZG1w0
https://pastebin.com/iMWWWX45
https://pastebin.com/kkXsbs97
https://pastebin.com/UHBCatn5
https://pastebin.com/DPcpNeZ9
https://pastebin.com/fHHtBFjd
https://pastebin.com/vF8j31Zh
https://pastebin.com/nhyQZdu9
https://pastebin.com/mtfhS7Aj
https://pastebin.com/3FUNwrvp
https://pastebin.com/G319X6pF
https://pastebin.com/Z1qQrwvm
https://pastebin.com/R6ZB19ty
https://pastebin.com/EnqXydWx
https://pastebin.com/gksC3F9Z
https://pastebin.com/Cykq1DBs
https://pastebin.com/bQGs5ax7
https://pastebin.com/D16eEKuP
https://pastebin.com/BGe2UhVN
https://pastebin.com/TBiEYzjP
https://pastebin.com/kRrGUbNx
https://pastebin.com/TeEd7AWP
https://pastebin.com/WkPsB9jV
https://pastebin.com/75rTmi6b
https://pastebin.com/55iYEkwJ
https://pastebin.com/ABhf0cQT
https://pastebin.com/Wck8UBrg
https://pastebin.com/HvufGqe1
https://pastebin.com/aGf21zJa
https://pastebin.com/1KC0r2dV
https://pastebin.com/mSZCaNsy
https://pastebin.com/PHY0NhKz
https://pastebin.com/hLvSK5h3
https://pastebin.com/8vdeEbVt
https://pastebin.com/aMvw36xu
https://pastebin.com/scWXT1Ww
https://pastebin.com/gj4zkeds
https://pastebin.com/07arVpkG
https://pastebin.com/XBe8122A
https://pastebin.com/wKmMhjbH
https://pastebin.com/ByJkH73m
https://pastebin.com/kaLTELa4
https://pastebin.com/ixKBaG55
https://pastebin.com/jJtu6cJU
https://pastebin.com/uiN7x6eW
https://pastebin.com/0wjd36gB
https://pastebin.com/LpG90XVK
https://pastebin.com/5wjiGR2X
https://pastebin.com/Y1v9SJfG
https://pastebin.com/f5ujh2b9
https://pastebin.com/jFr7dQQP
0 个评论
要回复文章请先登录或注册