HarmonyOS 鸿蒙Next Tabs的tabbar悬停效果
HarmonyOS 鸿蒙Next Tabs的tabbar悬停效果
Scroll 的示例3 ,tabbar 悬停效果,如果顶部还有一个类似标题栏,要悬停到标题栏下方,不是悬停到屏幕顶部,该如何实现?
(⊙o⊙)?神奇,还可以这样,需要设置sticky()
这是电商页面经典的做法
学到了,谢谢(●’◡’●)
[@Entry](/user/Entry)
[@Component](/user/Component)
struct Index {
//tab的索引
[@State](/user/State) currentIndex: number = 0
//tab控制器
controller: TabsController = new TabsController()
build() {
Column() {
//标题
Row() {
Text(‘我是标题’)
}
.height(60)
.width(‘100%’)
.justifyContent(FlexAlign.Center)
.backgroundColor(’#007edb’)
<span class="hljs-comment">//滚动区域</span>
Scroll() {
<span class="hljs-comment">//scroll内唯一根组件</span>
Column() {
<span class="hljs-comment">//scroll Area</span>
Text(<span class="hljs-string">'scroll Area'</span>)
.width(<span class="hljs-string">'100%'</span>)
.height(<span class="hljs-number">200</span>)
.textAlign(TextAlign.Center)
.backgroundColor(<span class="hljs-string">'#007edb'</span>)
<span class="hljs-comment">//tab</span>
Column() {
<span class="hljs-comment">//自定义tabbar</span>
Row({ space: <span class="hljs-number">30</span> }) {
ForEach(<span class="hljs-built_in">Array</span>.from({ length: <span class="hljs-number">2</span> }), (item: number, index: number) => {
Text(`页签${index}`)
.height(<span class="hljs-number">50</span>)
.fontColor(<span class="hljs-keyword">this</span>.currentIndex == index ? <span class="hljs-string">'#f00'</span> : <span class="hljs-string">'#000'</span>)
.onClick(() => {
<span class="hljs-keyword">this</span>.currentIndex = index
<span class="hljs-keyword">this</span>.controller.changeIndex(<span class="hljs-keyword">this</span>.currentIndex)
})
Text(<span class="hljs-string">'|'</span>)
})
}
.backgroundColor(<span class="hljs-string">'#fff'</span>)
.width(<span class="hljs-string">'100%'</span>)
.justifyContent(FlexAlign.Center)
.position({ x: <span class="hljs-number">0</span>, y: <span class="hljs-number">0</span> }) <span class="hljs-comment">//tabbar绝对定位0,0</span>
.zIndex(<span class="hljs-number">1</span>)
<span class="hljs-comment">//真正的tab</span>
Tabs({ controller: <span class="hljs-keyword">this</span>.controller }) {
TabContent() {
Scroll() {
Column() {
Text(<span class="hljs-string">'可能被tabbar遮住的内容'</span>)
.height(<span class="hljs-number">60</span>)
.backgroundColor(<span class="hljs-string">'#666'</span>)
Text(<span class="hljs-string">'内容1'</span>)
.width(<span class="hljs-string">'100%'</span>)
.fontSize(<span class="hljs-number">30</span>)
.height(<span class="hljs-number">1500</span>)
.textAlign(TextAlign.Center)
.backgroundColor(<span class="hljs-string">'#999'</span>)
}
}
.nestedScroll({
<span class="hljs-comment">//设置向上推时父子组件一起滚动</span>
scrollForward: NestedScrollMode.PARALLEL,
<span class="hljs-comment">//设置向下拉时父组件优先滚动</span>
scrollBackward: NestedScrollMode.PARENT_FIRST
})
}
TabContent() {
Scroll() {
Text(<span class="hljs-string">'内容2'</span>)
.width(<span class="hljs-string">'100%'</span>)
.fontSize(<span class="hljs-number">30</span>)
.height(<span class="hljs-number">1500</span>)
.textAlign(TextAlign.Center)
.backgroundColor(<span class="hljs-string">'#999'</span>)
}
}
}
.margin({ top: <span class="hljs-number">50</span> }) <span class="hljs-comment">//将被tabbar定位遮住的部分露出来</span>
.barHeight(<span class="hljs-number">0</span>) <span class="hljs-comment">//设置tabs自带tabbar的高为0</span>
.onChange(index => {
<span class="hljs-keyword">this</span>.currentIndex = index
})
}
}
}
.width(<span class="hljs-string">'100%'</span>)
.layoutWeight(<span class="hljs-number">1</span>)
}
.width(<span class="hljs-string">'100%'</span>)
.height(<span class="hljs-string">'100%'</span>)
.backgroundColor(<span class="hljs-string">'#f6f6f6'</span>)
}
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
你可以拿这段看看是不是你要的效果
我想要整个屏幕内都能滑动,一开始顶部 “我是标题” 这块是透明的,只是滑动一定的距离后这块才不透明了,并且tabbar滑动到 这块卡到这
@Entry @Component struct Index { //tab的索引 @State currentIndex: number = 0 //tab控制器 controller: TabsController = new TabsController() scrollScroller: Scroller = new Scroller() @State scrollOffset: number = 0
build() { Column() { //标题 Row() { Text(‘我是标题’) } .height(60) .width(‘100%’) .justifyContent(FlexAlign.Center) .backgroundColor(this.scrollOffset > 100 ? ‘#007edb’ : Color.Transparent) .animation({ duration: 300 })
//滚动区域
Scroll(this.scrollScroller) {
//scroll内唯一根组件
Column() {
//scroll Area
Text('scroll Area')
.width('100%')
.height(200)
.textAlign(TextAlign.Center)
.backgroundColor('#007edb')
//tab
Column() {
//自定义tabbar
Row({ space: 30 }) {
ForEach(Array.from({ length: 2 }), (item: number, index: number) => {
Text(`页签${index}`)
.height(50)
.fontColor(this.currentIndex == index ? '#f00' : '#000')
.onClick(() => {
this.currentIndex = index
this.controller.changeIndex(this.currentIndex)
})
Text('|')
})
}
.backgroundColor('#fff')
.width('100%')
.justifyContent(FlexAlign.Center)
.position({ x: 0, y: 0 }) //tabbar绝对定位0,0
.zIndex(1)
//真正的tab
Tabs({ controller: this.controller }) {
TabContent() {
Scroll() {
Column() {
Text('可能被tabbar遮住的内容')
.height(60)
.backgroundColor('#666')
Text('内容1')
.width('100%')
.fontSize(30)
.height(1500)
.textAlign(TextAlign.Center)
.backgroundColor('#999')
}
}
.nestedScroll({
//设置向上推时父子组件一起滚动
scrollForward: NestedScrollMode.PARALLEL,
//设置向下拉时父组件优先滚动
scrollBackward: NestedScrollMode.PARENT_FIRST
})
}
TabContent() {
Scroll() {
Text('内容2')
.width('100%')
.fontSize(30)
.height(1500)
.textAlign(TextAlign.Center)
.backgroundColor('#999')
}
}
}
.margin({ top: 50 }) //将被tabbar定位遮住的部分露出来
.barHeight(0) //设置tabs自带tabbar的高为0
.onChange(index => {
this.currentIndex = index
})
}
}
}
.width('100%')
.layoutWeight(1)
.onScroll(() => {
this.scrollOffset = this.scrollScroller.currentOffset().yOffset
})
}
.width('100%')
.height('100%')
.backgroundColor('#f6f6f6')
} } 再去试试
如果需要我是标题,压在scorllArea上,就绝对定位一下,zIndex设置一下
这个实现成功了吗?我现在也要实现这种效果,求回复
enum ScrollPosition {
start,
center,
end
}
[@Entry](/user/Entry)
[@Component](/user/Component)
struct IndexPage {
[@State](/user/State) listPosition: number = ScrollPosition.start
[@State](/user/State) scrollPosition: number = ScrollPosition.start
[@State](/user/State) showTitle: boolean = false
[@State](/user/State) currentYOffset: number = 0
[@State](/user/State) opacityNumber: number = 1
[@State](/user/State) currentScrollOffsetInList: number = 0
private currentScrollStateInList: ScrollState | null = null
[@State](/user/State) msg1: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[@State](/user/State) msg2: string[] = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
[@State](/user/State) msg3: string[] = ['aa', 'bb', 'cc', 'dd', 'ee', 'ff', 'gg', 'hh', 'ii', 'jj']
private scrollerForScroll: Scroller = new Scroller()
private scrollerForList: Scroller = new Scroller()
scrollGetData: number[] = []
private lastOffset: number = 0
build() {
Stack({ alignContent: Alignment.Top }) {
Scroll(this.scrollerForScroll) {
Column() {
Image($r('app.media.startIcon'))
.width('100%')
.height('40%')
Tabs({ barPosition: BarPosition.Start }) {
TabContent() {
Column() {
List({ space: 10, scroller: this.scrollerForList }) {
ForEach(this.msg3, (item: string) => {
ListItem() {
Text('ListItem' + item)
.width('100%')
.height('100%')
.borderRadius(15)
.fontSize(24)
.textAlign(TextAlign.Center)
.backgroundColor(Color.White)
}
.width('100%')
.height(100)
}, (item: string) => item)
}
.padding({ left: 10, right: 10 })
.width('100%')
.edgeEffect(EdgeEffect.None)
.scrollBar(BarState.Off)
.onReachStart(() => {
this.listPosition = ScrollPosition.start
})
.onReachEnd(() => {
this.listPosition = ScrollPosition.end
})
.onScrollFrameBegin((offset: number, state: ScrollState) => {
// 滑动到列表中间时
if (!((this.listPosition == ScrollPosition.start && offset < 0)
|| (this.listPosition == ScrollPosition.end && offset > 0))) {
this.listPosition = ScrollPosition.center
}
// 如果页面已滚动到底部,列表不在顶部或列表有正向偏移量
if (this.scrollPosition == ScrollPosition.end
&& (this.listPosition != ScrollPosition.start || offset > 0)) {
return { offsetRemain: offset };
} else {
this.scrollerForScroll.scrollBy(0, offset)
return { offsetRemain: 0 };
}
})
.onScroll((scrollOffset: number, scrollState: ScrollState) => {
this.currentScrollOffsetInList = scrollOffset
this.currentScrollStateInList = scrollState
if (scrollOffset != 0) {
this.lastOffset = scrollOffset
}
//记录打印0前的最后一个值
console.log(this.lastOffset + ' this.lastOffset')
console.log(scrollOffset + '');
(scrollOffset <= 0 && this.lastOffset < 0) ? this.showTitle = true : this.showTitle = false
})
}
}.tabBar('你好')
TabContent() {
Column().width('100%').height('100%').backgroundColor('#007DFF')
}.tabBar('好的')
}
.vertical(false)
.barMode(BarMode.Fixed)
.barWidth(360)
.barHeight(56)
.width("100%")
.height("92%")
.backgroundColor('#F1F3F5')
}
}
.scrollBar(BarState.Off)
.width('100%')
.height('100%')
.onScroll((xOffset: number, yOffset: number) => {
this.currentYOffset = this.scrollerForScroll.currentOffset().yOffset
console.log("this.currentYOffset => " + this.currentYOffset)
let opacityNum = 1 - this.currentYOffset / 249
if (opacityNum > 0) {
this.opacityNumber = opacityNum
}
else {
this.opacityNumber = 0
}
// 非(页面在顶部或页面在底部),则页面在中间
if (!((this.scrollPosition == ScrollPosition.start && yOffset < 0)
|| (this.scrollPosition == ScrollPosition.end && yOffset > 0))) {
this.scrollPosition = ScrollPosition.center
}
})
.onScrollEdge((side: Edge) => { // 滚动到边缘事件回调
if (side == Edge.Top) {
// 页面在顶部
this.scrollPosition = ScrollPosition.start
} else if (side == Edge.Bottom) {
// 页面在底部
this.scrollPosition = ScrollPosition.end
}
})
.onScrollFrameBegin(offset => {
if (this.scrollPosition = ScrollPosition.end) {
return { offsetRemain: 0 }
} else {
return { offsetRemain: offset }
}
})
Stack() {
Row() {
Text('Title')
.fontSize(24)
}
.justifyContent(FlexAlign.Center)
}
.opacity(this.opacityNumber)
.backgroundColor(Color.Red)
.width('100%')
.height('8%')
}
.width('100%')
.height('100%')
.backgroundColor(0xDCDCDC)
}
}
官方大佬给的示例,需要的可以看下
感觉怪怪的),title的隐藏时机是不是反了(捂脸
是的,给的反的
想要在整个屏幕内都可以滑动,让tabbar一块滑动,并且滑动到标题栏能悬停到那里,绝对定位到0,0固定那不行
我的思路是 ,tab和tabbar放在一个colume里边,tabbar绝对定位 ,让colume的高等于 屏幕的高 减去 标题的高 ,那tabbar就会停在标题栏的下边(因为colum的高就到标题栏下边,然后tabcontent的内容滚动,tabbar一直在colume的0,0位置,tabcontent的内容滚动也不会影响到tabbar,我觉得应该可以
这个有实现的代码吗?
HarmonyOS 鸿蒙Next Tabs的tabbar悬停效果可以通过自定义实现。通常,你需要使用List包裹Tabs,并自定义Tab头,将其放入ListItemGroup中。同时,设置sticky()属性以实现悬停效果。确保Tabbar在滚动时能够固定在屏幕上的特定位置,如标题栏下方。如果问题依旧没法解决,请加我微信,我的微信是itying888。