HarmonyOS鸿蒙Next中使用nestedScroll进行吸顶时,内层的list内容显示不全,不能给list加layoutWeight(1),如何解决
HarmonyOS鸿蒙Next中使用nestedScroll进行吸顶时,内层的list内容显示不全,不能给list加layoutWeight(1),如何解决
@Entry
@Component
struct Index {
build() {
Scroll() {
Column() {
Text('其他UI内容')
.width('100%')
.height(850)
.textAlign(TextAlign.Center)
.backgroundColor('#c900f7ff')
Column() {
Text('这是吸顶标题')
.width('100%')
.height(50)
.fontSize(20)
.textAlign(TextAlign.Center)
.backgroundColor('#1f000000')
List({ space: 5 }) {
ForEach(Array.from({ length: 1 }), (item: undefined, index: number) => {
ListItem() {
Text('这是列表项')
}
.width('100%')
.height(50)
.padding({ left: 5, right: 5 })
.backgroundColor('#aeefc901')
})
}
.layoutWeight(1)
.alignListItem(ListItemAlign.Center)
.nestedScroll({
scrollForward: NestedScrollMode.PARENT_FIRST,
scrollBackward: NestedScrollMode.SELF_FIRST
})
}
.constraintSize({ maxHeight: '100%' })
}
}
.width('100%')
.height('100%')
.align(Alignment.Top)
}
}
更多关于HarmonyOS鸿蒙Next中使用nestedScroll进行吸顶时,内层的list内容显示不全,不能给list加layoutWeight(1),如何解决的实战教程也可以访问 https://www.itying.com/category-93-b0.html
问题描述
如何在HarmonyOS中实现标题吸顶效果?
背景知识
吸顶效果(Sticky Effect 或 Fixed on Scroll)是网页开发中的一种常见交互设计,指当用户滚动页面时,某个元素(如导航栏、标题栏、工具栏等)会固定在浏览器窗口的顶部(或其他指定位置),保持始终可见,不会随着页面滚动而消失。这种效果能提升用户体验,方便用户快速访问关键功能(如购物商城导航菜单、返回顶部按钮等)。在开发过程中,吸顶效果通常用于需要保持关键元素始终可见的场景,以提升用户体验和操作效率。以下是一些典型应用场景及具体需求:
- 导航栏场景:电商网站顶部分类导航、博客网站的目录跳转;
- 长表格的表头:金融数据报表、后台管理系统中的列表页;
- 分类筛选栏:电商商品列表的“价格排序”、内容平台的“标签筛选”;
- 广告或通知栏:持续展示广告场景。
在HarmonyOS中有多种实现吸顶效果的方案,以及不同的吸顶效果,不同方案及需要了解的知识如下:
-
普通吸顶效果:标题一直附着在页面顶部或底部,不随着页面滚动:
- 通过[a href=“https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs” target="_blank"]Tabs[/a]的tabBar属性或自定义标题栏组件,实现吸顶效果。
-
滚动嵌套吸顶效果:标题本身在滚动组件内部,能跟随滚动组件移动。同时在滚动到顶部时,吸附在顶部,不随后续滚动消失:
- 通过父子组件的滚动联动实现吸顶效果。
-
父子组件的滚动联动效果实现,由滚动通用属性[a href=“https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-list#nestedscroll10” target="_blank"]nestedScroll属性[/a]控制。nestedScroll属性的参数NestedScrollMode分为以下四类:
参数类型 效果 SELF_ONLY 只自身滚动,不与父组件联动。 SELF_FIRST 自身先滚动,自身滚动到边缘以后父组件滚动。父组件滚动到边缘以后,如果父组件有边缘效果,则父组件触发边缘效果,否则子组件触发边缘效果。 PARENT_FIRST 父组件先滚动,父组件滚动到边缘以后自身滚动。自身滚动到边缘后,如果有边缘效果,会触发自身的边缘效果,否则触发父组件的边缘效果。 PARALLEL 自身和父组件同时滚动,自身和父组件都到达边缘以后,如果自身有边缘效果,则自身触发边缘效果,否则父组件触发边缘效果。
- 通过[a href=“https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-list” target="_blank"]List组件[/a]的[a href=“https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-list#sticky9” target="_blank"]sticky[/a]属性实现吸顶效果。
-
该方案需要配合[a href=“https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-listitemgroup” target="_blank"]ListItemGroup组件[/a]使用,设置ListItemGroup中header和footer是否要吸顶或吸底。sticky属性参数类型如下:
类型 值 效果 StickyStyle.None 0 ListItemGroup的header不吸顶,footer不吸底。 StickyStyle.Header 1 ListItemGroup的header吸顶,footer不吸底。 StickyStyle.Footer 2 ListItemGroup的footer吸底,header不吸顶。
解决方案
-
普通吸顶效果:
- 方案一:通过Tabs组件的tabBar属性实现吸顶效果。在实施过程中有时我们也可以自定义实现Tabs效果。
@Entry @Component export struct Index { subsController: TabsController = new TabsController() @State arr: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'] build() { Tabs({ barPosition: BarPosition.Start, controller: this.subsController }){ TabContent(){ List({ space: 10 }){ ForEach(this.arr, (item: number) => { ListItem(){ Row(){ Text('item' + item) .fontSize(16) .height(72) .fontColor(Color.Black) } .width('100%') .height(72) .justifyContent(FlexAlign.Center) } .borderRadius(15) .backgroundColor(Color.White) }, (item: string) => item) } .padding({ left: 10, right: 10 }) .width('100%') .height('100%') .scrollBar(BarState.Off) } .tabBar('关注') .backgroundColor(Color.Gray) TabContent(){ Text('推荐') } .tabBar('推荐') .backgroundColor(Color.White) } .backgroundColor('#6dbab8b8') } }
- 方案二:自定义标题的吸顶实现,该方案在实际软件中若要实现Tabs页面切换效果,需要自定义页面切换逻辑(页面切换与本知识无关,不再赘述)。
@Entry @Component struct ScrollerTest { subsController: TabsController = new TabsController() @State arr: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'] build() { Column() { Row() { // 吸顶标题 Text('自定义占位标题') .width('100%') .height(60) .backgroundColor('#ff736c6c') } List({ space: 10 }){ // ... } .layoutWeight(1) // 更换List组件height属性,高度限制以layoutWeight(1)的形式自动填充父组件高度 } .width('100%') .height('100%') // 普通吸顶效果时,滚动组件的父组件可以不设置高度,但是滚动嵌套吸顶时一定要设置高度限制为100% .backgroundColor('#6dbab8b8') } }
- 方案一:通过Tabs组件的tabBar属性实现吸顶效果。在实施过程中有时我们也可以自定义实现Tabs效果。
-
单标题滚动嵌套吸顶效果:
- 通过nestedScroll属性,实现吸顶效果。由于nestedScroll属性是滚动与滑动组件的通用属性,理论上在滚动组件嵌套的过程中,支持该属性的滚动组件都可以实现吸顶效果。以Tabs组件为例,参考代码如下:
@Entry @Component struct ScrollerTest { subsController: TabsController = new TabsController() @State arr: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'] build() { Scroll() { Column() { Column() { Text('广告展示/搜索选择等') .fontSize(30) .width('100%') .height(200) .backgroundColor('#ff0296a4') .textAlign(TextAlign.Center) } Tabs({ barPosition: BarPosition.Start, controller: this.subsController }) { TabContent() { List({ space: 10 }){ ForEach(this.arr, (item: number) => { ListItem(){ Row(){ Text('item' + item) .fontSize(16) .height(72) .fontColor(Color.Black) } .width('100%') .height(72) .justifyContent(FlexAlign.Center) } .borderRadius(15) .backgroundColor(Color.White) }, (item: string) => item) } .padding({ left: 10, right: 10 }) .width('100%') .height('100%') .scrollBar(BarState.Off) .nestedScroll({ scrollForward: NestedScrollMode.PARENT_FIRST, // 向上滚动PARENT_FIRST:父组件先滚动,父组件滚动到边缘以后自身滚动。 scrollBackward: NestedScrollMode.SELF_FIRST // 向下滚动SELF_FIRST:自身先滚动,自身滚动到边缘以后父组件滚动。 }) } .tabBar('关注') .backgroundColor(Color.Gray) TabContent(){ Text('推荐') } .tabBar('推荐') .backgroundColor(Color.White) } .backgroundColor('#6dbab8b8') } } .width('100%') .edgeEffect(EdgeEffect.Spring) .friction(0.6) .backgroundColor(Color.White) .scrollBar(BarState.Off) .width('100%') .height('100%') } }
- 通过nestedScroll属性,实现吸顶效果。由于nestedScroll属性是滚动与滑动组件的通用属性,理论上在滚动组件嵌套的过程中,支持该属性的滚动组件都可以实现吸顶效果。以Tabs组件为例,参考代码如下:
-
多标题滚动嵌套吸顶效果
-
方案一:通过nestedScroll属性对滚动组件多次滚动嵌套,参考单标题滚动嵌套吸顶效果,修改的核心代码如下:
@Entry @Component struct ScrollerTest { subsController: TabsController = new TabsController() @State arr: string[] = ['1', '2', '3'] @State arr1: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15'] build() { Scroll() { Column() { // ...(省略广告展示/搜索选择标题部分代码) Column() { Row() { Text('自定义标题占位') // 自定义实现标题吸顶,依旧采用Tabs组件也适用 .fontSize(16) .height(60) .width('100%') } Scroll() { Column() { ForEach(this.arr, (item: number) => { Row() { Text('item' + item) .fontSize(16) .height(72) .fontColor(Color.Black) } .width('100%') .height(72) .borderRadius(15) .margin({ bottom: 10 }) .justifyContent(FlexAlign.Center) }, (item: string) => item) // ...(省略单标题滚动嵌套吸顶效果代码中Tabs组件代码) } .backgroundColor(Color.White) .width('100%') } .width('100%') .height('100%') .scrollBar(BarState.Off) .nestedScroll({ scrollForward: NestedScrollMode.PARENT_FIRST, // 向上滚动PARENT_FIRST:父组件先滚动,父组件滚动到边缘以后自身滚动。 scrollBackward: NestedScrollMode.SELF_FIRST // 向下滚动SELF_FIRST:自身先滚动,自身滚动到边缘以后父组件滚动。 }) } .height('100%') // 由于是自定义的标题,所以容纳标题和列表的父组件一定要设置高度为100% .backgroundColor('#6dbab8b8') } } .width('100%') } // ... }
-
方案二:通过List组件的sticky属性,实现吸顶效果。
- 该方案仅适用于List组件,具体实施方案参考官方示例:吸顶/吸底。
-
常见FAQ
Q:还有其他组件能实现吸顶效果吗? A:可以通过[a href=“https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-stack” target="_blank"]Stack组件[/a]或者[a href=“https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-universal-attributes-z-order#zindex” target="_blank"]zIndex[/a]属性,这类层叠布局实现组件吸顶。但这类层叠方式,该场景下并不常见,该方式更多用于网页中的客服按钮/回到页面顶部等场景。
Q:如何实现滑动时吸顶标题组件颜色渐变的效果? A:可以通过[a href=“https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-scrollable-common#ondidscroll12” target="_blank"]onDidScroll[/a]等监听滑动的事件,监听组件的偏移量,从而控制吸顶的标题组件改变透明度、背景颜色等状态。
总结
分类 | 普通吸顶效果 | 单标题滚动嵌套吸顶效果 | 多标题滚动嵌套吸顶效果 |
---|---|---|---|
实现方式 | Tabs或自定义标题栏 | nestedScroll属性滚动嵌套Tabs或自定义标题栏 | nestedScroll属性滚动嵌套Tabs或自定义标题栏/List组件的sticky属性 |
自定义吸顶标题时易错问题 | 自定义标题栏时Scroll等滚动组件没有设置高度限制导致滚动组件超出安全区。其最大自适应高度为屏幕的百分百高度,可以设置heght属性或者layoutWeight(1)属性限制高度。 | 滚动组件的父组件一定要设置高度限制为100%,若不设置高度限制,父组件自适应高度会导致吸顶失效,因为滚动组件的最大自适应高度为屏幕的100%高度,当滚动组件子组件高度和大于屏幕的百分百时,滚动组件高度自适应100%高度,会将标题顶出屏幕外,导致吸顶失效。 | 当采用nestedScroll属性滚动嵌套实现时,与“单标题滚动嵌套吸顶效果”需要注意相似问题。 |
适用场景 | 适用于所有的带标题的软件场景 | 微信朋友圈等类似场景 | 电商软件主页场景 |
更多关于HarmonyOS鸿蒙Next中使用nestedScroll进行吸顶时,内层的list内容显示不全,不能给list加layoutWeight(1),如何解决的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
您好,为了更快速解决您的问题,并且吸引更多用户一同参与您问题的解答与讨论,建议您补全如下信息:
补全复现代码(如最小复现demo、脚本),让参与用户更快速复现您的问题;
更多提问技巧,请参考:《提问小技巧:让解答更高效》
在HarmonyOS Next中,当使用nestedScroll
实现吸顶效果时,List内容显示不全的问题可以通过以下方式解决:
- 移除
constraintSize
约束,改用flex布局:
Column() {
Text('这是吸顶标题')
// ...其他样式
List({ space: 5 }) {
// ...列表内容
}
.width('100%')
.height('100%') // 关键修改点
.nestedScroll({
scrollForward: NestedScrollMode.PARENT_FIRST,
scrollBackward: NestedScrollMode.SELF_FIRST
})
}
- 如果必须使用
constraintSize
,可以改为设置minHeight
而非maxHeight
:
.constraintSize({ minHeight: '100%' })
- 确保父容器
Scroll
有明确的高度约束,如:
Scroll() {
// 内容
}
.height('100%')
这些修改能让List获得正确的布局空间,同时保持nestedScroll
的吸顶效果。注意在Column
容器中,子组件默认是垂直排列的,合理设置高度是关键。