问题现象
参照Scroll的示例3,实现了tabBar在页面顶部的悬停效果。
如果页面顶部还有一个标题栏(即下图中“首页”),现在要实现tab内容向上滚动时tabBar悬停到标题栏下方(即下图中“同城”,“推荐”,“活动”,“玩机”这一行),且可以实现标题栏在滚动过程中样式变化(如下图背景变化),该如何实现?
点击放大点击放大
背景知识
Stack:堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。
Scroll:可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。
nestedScroll:设置前后两个方向的嵌套滚动模式,实现与父组件的滚动联动。
onDidScroll:滚动事件回调,Scroll滚动时触发。
解决方案
使用Stack层叠布局,将标题栏悬浮展示在页面顶部。
考虑页面滚动以及tabContent里面的list滚动,就要考虑滚动嵌套问题,目前场景需要选择:
向上滚动时:父组件先滚动,父组件滚动到边缘以后自身滚动;
向下滚动时:自身先滚动,自身滚动到边缘以后父组件滚动。
示例代码如下:
.nestedScroll({
scrollForward: NestedScrollMode.PARENT_FIRST,
scrollBackward: NestedScrollMode.SELF_FIRST
});
父组件滚动过程中,根据滚动偏移量线性修改标题栏样式(如字体大小、透明度、背景等),onDidScroll可以返回当前帧滚动的偏移量和当前滚动状态。
示例代码如下:
@Entry
@Component
struct StickyNestedScroll {
@State arr: number[] = [];
@State opacityNum: number = 0;
@State curYOffset: number = 0;
@State currentIndex: number = 0;
aboutToAppear() {
for (let i = 0; i < 30; i++) {
this.arr.push(i);
}
}
@Styles
listCard() {
.backgroundColor('#FFF')
.height(64)
.width('calc(100% - 32vp)')
.borderRadius(20)
.margin({
left: 16,
right: 16,
});
}
@Builder
tabBuilder(title: string, targetIndex: number) {
Column() {
Text(title)
.fontColor(this.currentIndex === targetIndex ? '#FFF' : '#000')
.fontSize(14)
.fontWeight(this.currentIndex === targetIndex ? 500 : 400);
}
.height(36)
.padding({
left: 16,
right: 16,
})
.margin({ left: 8 })
.borderRadius(20)
.backgroundColor(this.currentIndex === targetIndex ? '#0A59F7' : 'rgba(0, 0, 0, 0.05)')
.alignItems(HorizontalAlign.Center)
.justifyContent(FlexAlign.Center);
}
build() {
Stack() {
Scroll() {
Column() {
Image($r('app.media.scrollTopbg')) // 图片资源需自行替换
.width('100%')
.height(300);
Tabs({ barPosition: BarPosition.Start }) {
ForEach(this.arr.slice(0, 6),
(item: number, index: number) => {
TabContent() {
List({ space: 16 }) {
ForEach(this.arr, (item1: number) => {
ListItem() {
Text('item' + item1)
.fontSize(16).fontWeight(400);
}.listCard();
}, (item1: string) => item1);
}.width('100%')
.edgeEffect(EdgeEffect.None)
.nestedScroll({
scrollForward: NestedScrollMode.PARENT_FIRST,
scrollBackward: NestedScrollMode.SELF_FIRST
});
}.tabBar(this.tabBuilder(`标签${item + 1}`, index));
}, (item: number, index: number) => JSON.stringify(item) + index);
}
.onChange((index) => {
this.currentIndex = index;
})
.barMode(BarMode.Scrollable)
.barHeight(72)
.vertical(false)
.width('100%')
.height('calc(100% - 80vp)');
}.width('100%');
}
.friction(0.6)
.scrollBar(BarState.Off)
.width('100%')
.height('100%')
.onDidScroll((xOffset: number, yOffset: number, scrollState: ScrollState): void => {
// 累计计算当前父组件滚动在Y轴方向的偏移量
this.curYOffset += yOffset;
// 根据父组件一共可以滚动的距离计算当前每帧的当前透明度
let opacity = this.curYOffset / 220;
if (opacity >= 1) {
opacity = 1;
}
if (opacity <= 0) {
opacity = 0;
}
this.opacityNum = opacity;
console.info(`xOffset: ${xOffset},scrollState:${scrollState}`);
});
// 悬浮标题栏
Text('工作台')
.fontSize(24)
.fontColor('#000')
.fontWeight(FontWeight.Bold)
.backgroundColor(`rgba(255,255,255,${this.opacityNum})`)
.position({ x: 0, y: 0 })
.width('100%')
.height(80)
.padding({ left: 16, top: 44 });
}.width('100%')
.height('100%').background('#F1F3F5');
}
}
效果如图:
点击放大
总结
悬浮类布局首先考虑Stack层叠布局。
嵌套滚动,考虑父子组件之间的先后滚动模式,选择合适的滚动模式。
滚动过程中,获取当前滚动每帧偏移量和滚动状态,做合适的UI更新。
https://pastebin.com/H9s5Prqc
https://pastebin.com/B3rdpE0P
https://pastebin.com/1DnHtpyd
https://pastebin.com/TEdBHtNb
https://pastebin.com/LJ0cQ7Uu
https://pastebin.com/bEc1mLCD
https://pastebin.com/kgSG3Gqx
https://pastebin.com/562Mtrb0
https://pastebin.com/TcJ1ucZM
https://pastebin.com/NdYhTKwU
https://pastebin.com/0kg2myHE
https://pastebin.com/tuXkKyRR
https://pastebin.com/JNaUA51y
https://pastebin.com/RqerbF2p
https://pastebin.com/jzeTmGu6
https://pastebin.com/bG1T2kG0
https://pastebin.com/2waPB0AK
https://pastebin.com/miLDPTFG
https://pastebin.com/2GVXUYr6
https://pastebin.com/RDfika4N
https://pastebin.com/yVTUxb9T
https://pastebin.com/8fpFzpMF
https://pastebin.com/dxrwgxZb
https://pastebin.com/WW5LdheP
https://pastebin.com/j9dwuCiX
https://pastebin.com/4pjqADUq
https://pastebin.com/RMeYiqCG
https://pastebin.com/jcEZ3mCw
https://pastebin.com/u0UKBHMc
https://pastebin.com/6AtALgcG
https://pastebin.com/yZZZgpRJ
https://pastebin.com/LbQCHdWp
https://pastebin.com/8uaaUxm3
https://pastebin.com/smKGwEkJ
https://pastebin.com/XZS8Lgc9
https://pastebin.com/PXPcxxu5
https://pastebin.com/AzHkpzSh
https://pastebin.com/kdDFUmsj
https://pastebin.com/ejETYeux
https://pastebin.com/s4Tj7hqX
https://pastebin.com/n8vn16hR
https://pastebin.com/cUBURDS5
https://pastebin.com/iHuTYWub
https://pastebin.com/it84K7XW
https://pastebin.com/dHhXdDc4
https://pastebin.com/btsEnW55
https://pastebin.com/VhQvwq6f
https://pastebin.com/prMTmsc5
https://pastebin.com/giVp1BpF
https://pastebin.com/fQyYpmGY
https://pastebin.com/gAg3F6UY
https://pastebin.com/2QWLCNvx
https://pastebin.com/2gxy4TKg
https://pastebin.com/xKYNRWMk
https://pastebin.com/1HxCD5DS
https://pastebin.com/GiAXtWj1
https://pastebin.com/m8afMq62
https://pastebin.com/55Xb4vqW
https://pastebin.com/zJcq0WY7
https://pastebin.com/WmVwfQrY
https://pastebin.com/91bnWbQF
https://pastebin.com/gvKhZ9Tc
https://pastebin.com/Nt21BqQ7
https://pastebin.com/wM2aTQ0w
https://pastebin.com/Vc7vvzKJ
https://pastebin.com/yaq33eZQ
https://pastebin.com/qZ5F9NYb
https://pastebin.com/i3E4FgCp
https://pastebin.com/AkTA5RZZ
https://pastebin.com/ELEG1B0m
https://pastebin.com/5JWdPFhR
https://pastebin.com/R0YTHUS4
https://pastebin.com/x9nRf1j0
https://pastebin.com/Aih0qsy2
https://pastebin.com/CpwvWE4e
https://pastebin.com/rr9rRU2E
https://pastebin.com/6Ye4Gwq7
https://pastebin.com/DAw6tKSy
https://pastebin.com/6gFkNdxP
https://pastebin.com/zMtnD7tM
https://pastebin.com/95F1ruf8
https://pastebin.com/ZXeMfgMs
https://pastebin.com/s8Xu4WDd
https://pastebin.com/cTfEk1wu
https://pastebin.com/Mjm4d4Rz
https://pastebin.com/gRAQUhkK
https://pastebin.com/YpNWSg6u
https://pastebin.com/51Edu6ba
https://pastebin.com/XkAuM8JZ
https://pastebin.com/vcnnDhb9
https://pastebin.com/hjhUzWgG
https://pastebin.com/Za2eji2y
https://pastebin.com/6HcM5ez2
https://pastebin.com/iKpg8iex
https://pastebin.com/9zDKuETK
https://pastebin.com/M4swhPLu
https://pastebin.com/BFs6X9UX
https://pastebin.com/GWjxjEgb
https://pastebin.com/E1LbLCgp
https://pastebin.com/Ze95QMAi
https://pastebin.com/ZY8zYNWn
https://pastebin.com/fTLHPLZZ
https://pastebin.com/6fDk9tYi
https://pastebin.com/GfuDHVfH
https://pastebin.com/KUq4BLce
https://pastebin.com/qY5k2ZxX
https://pastebin.com/8yXshjhD
https://pastebin.com/3BmddLGG
https://pastebin.com/6hgiPSQy
https://pastebin.com/pwCxCvBx
https://pastebin.com/rdgB20Hq
https://pastebin.com/fR1AXxN3
https://pastebin.com/XAyJJSh4
https://pastebin.com/Udz89NF9
https://pastebin.com/tRFNRTfq
https://pastebin.com/LYnbJkDX
https://pastebin.com/UrndZZ4r
https://pastebin.com/UJ0cJu7W
https://pastebin.com/VC9ftumY
https://pastebin.com/1mD57fxS
https://pastebin.com/4yCvSzPt
https://pastebin.com/Tds1KK8q
https://pastebin.com/cuTV0ANH
https://pastebin.com/tfvAj5zG
https://pastebin.com/YmTJJ9P4
https://pastebin.com/qr720c8a
https://pastebin.com/Qzx9z0jT
https://pastebin.com/phurPJTs
https://pastebin.com/gHHTkHD3
https://pastebin.com/ZwnPCDTj
https://pastebin.com/0DSjtHAt
https://pastebin.com/TftyJMxx
https://pastebin.com/vBBJvgLm
https://pastebin.com/NQYakApj
https://pastebin.com/meCbWSmb
https://pastebin.com/1VP7BDiy
https://pastebin.com/9dwnBKrH
https://pastebin.com/CfNxq9BD
https://pastebin.com/7SdTHhbB
https://pastebin.com/wjGatMb0
https://pastebin.com/Gv2kQv0K
https://pastebin.com/kqY5ZC2U
https://pastebin.com/NVQSYDC2
https://pastebin.com/p5cmmLTs
https://pastebin.com/ksUjWjEf
https://pastebin.com/iGqdf7JS
https://pastebin.com/1jPPW8SY
https://pastebin.com/zaiTAPGu
https://pastebin.com/ZyCEaVhf
https://pastebin.com/Z8nhRzGY
https://pastebin.com/4ANEqn0d
https://pastebin.com/B6aK9n6G
https://pastebin.com/0Tt4rGw1
https://pastebin.com/jV1WDDj1
https://pastebin.com/epsfQ9xR
https://pastebin.com/TDsuwVQq
https://pastebin.com/1sCfUZ1r
https://pastebin.com/rPZVVY9W
https://pastebin.com/YMAeatYs
https://pastebin.com/USZwiZLz
https://pastebin.com/0D4g5hpe
https://pastebin.com/aTgxSFAv
https://pastebin.com/d9yLduCs
https://pastebin.com/t2jGSt52
https://pastebin.com/ZCjZZ5cd
https://pastebin.com/fYBzqBQc
https://pastebin.com/rPSifbkZ
https://pastebin.com/r5hsmStB
https://pastebin.com/GBQJqUpA
https://pastebin.com/wi5TgU60
https://pastebin.com/17bmtrLm
https://pastebin.com/ymjx0ej6
https://pastebin.com/tnhPx5tx
https://pastebin.com/pKythJNa
https://pastebin.com/7rkBm8RR
https://pastebin.com/nKrgz0hx
https://pastebin.com/Ls4U30up
https://pastebin.com/GLrgZDKM
https://pastebin.com/QLenyQyb
https://pastebin.com/6kf7ctaD
https://pastebin.com/493xDX2E
https://pastebin.com/NNLBP1BA
https://pastebin.com/fQsBphT0
https://pastebin.com/iFUr5gqq
https://pastebin.com/YkZtGRGV
https://pastebin.com/CUgpDscE
https://pastebin.com/4BSRJRJ2
https://pastebin.com/rgaPPPXy
https://pastebin.com/e0MbXcLH
https://pastebin.com/0y661SPV
https://pastebin.com/WnhafHAL
https://pastebin.com/vdcuA6Wn
https://pastebin.com/0wP7iM13
https://pastebin.com/kSsbb7uN
https://pastebin.com/CKuHJUp0
https://pastebin.com/VFHuYY0w
https://pastebin.com/e57GMSyT
https://pastebin.com/JCJqt21y
https://pastebin.com/v03W6Wua
https://pastebin.com/Qh5cvmxD
https://pastebin.com/1n1rmrga
https://pastebin.com/EqpNrUd9
https://pastebin.com/hNzVc4VA
https://pastebin.com/wyd61PAX
https://pastebin.com/KUqAc0dA
https://pastebin.com/dAwvfQ3n
https://pastebin.com/tfhzjx0X
https://pastebin.com/qcry1nbc
https://pastebin.com/Xx1xKrr5
https://pastebin.com/z4RRXjbZ
https://pastebin.com/HFUs4bbZ
https://pastebin.com/7hFpzwBb
https://pastebin.com/kkxJEXkH
https://pastebin.com/8N244GbV
https://pastebin.com/6QgG0hC0
https://pastebin.com/SPfWYRk3
https://pastebin.com/CQQ6jn3J
https://pastebin.com/KHGYtVZu
https://pastebin.com/ibnJTTYm
0 个评论
要回复文章请先登录或注册