【鸿蒙 HarmonyOS NEXT】组件嵌套滚动:nestedScroll
✨本人自己开发的开源项目:土拨鼠充电系统
✨踩坑不易,还希望各位大佬支持一下,在GitHub给我点个 Start ⭐⭐👍👍
✍GitHub开源项目地址👉:https://github.com/cheinlu/groundhog-charging-system
一、背景
当滚动组件进行嵌套关系时,如果两个组件需要同时滚动可能会产生互斥效果,使用nestedScroll属性来解决嵌套组件的滚动问题
可滚动组件:Scroll、List、WaterFlow,这些组件中都有包含nestedScroll属性,用于解决组件嵌套的滚动联动
二、场景
tabs嵌套list组件,当tabs切换页签时,会与list组件的滚动出现互斥效果,期望按住文本或按钮区域都能实现切换页签效果
具体描述:
tabs下面展示文本信息与按钮,其中按钮是用list组件完成的,当按钮多的情况下是可以滚动按钮,目前问题是按住文本区域是可以左右切换tabs页签的,按住按钮区域切换tab就不行,怀疑是list滚动与tab页签切换互斥了
三、具体实现
3.1、示例代码
@Entry
@Component
struct TabsExample {@State fontColor: string = '#182431'@State selectedFontColor: string = '#007DFF'@State currentIndex: number = 0private controller: TabsController = new TabsController()@BuildertabBuilder(index: number, name: string) {Column() {Text(name).fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor).fontSize(16).fontWeight(this.currentIndex === index ? 500 : 400).lineHeight(22).margin({ top: 17, bottom: 7 })Divider().strokeWidth(2).color('#007DFF').opacity(this.currentIndex === index ? 1 : 0)}.width('100%')}build() {Column() {Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {TabContent() {OrderList({ type: '1' })}.tabBar(this.tabBuilder(0, 'green')).gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Right })))TabContent() {OrderList({ type: '2' })}.tabBar(this.tabBuilder(1, 'blue'))TabContent() {OrderList({ type: '3' })}.tabBar(this.tabBuilder(2, 'yellow'))TabContent() {OrderList({ type: '4' })}.tabBar(this.tabBuilder(3, 'pink')).gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Left })))}.vertical(false).barMode(BarMode.Fixed).barWidth(360).barHeight(56).animationDuration(400).onChange((index: number) => {this.currentIndex = index}).width(360).height(296).margin({ top: 52 }).backgroundColor('#F1F3F5')}.width('100%')}
}@Component
struct OrderList {@Prop type: stringbuild() {Column() {Column({ space: 30 }) {Row() {Text('文本' + this.type)}Row() {Text('文本' + this.type)}Row() {Text('文本' + this.type)}}.width('100%').height(150)List() {ListItem() {Row() {Text('取消订单' + this.type).fontSize(13).fontColor('#222427')}.padding({left: 12,right: 12,top: 5,bottom: 5}).border({width: 1,radius: 4,color: '#C9CED3',style: BorderStyle.Solid})}ListItem() {Row() {Text('查看发票' + this.type).fontSize(13).fontColor('#222427')}.padding({left: 12,right: 12,top: 5,bottom: 5}).border({width: 1,radius: 4,color: '#C9CED3',style: BorderStyle.Solid})}ListItem() {Row() {Text('申请发票' + this.type).fontSize(13).fontColor('#222427')}.padding({left: 12,right: 12,top: 5,bottom: 5}).border({width: 1,radius: 4,color: '#C9CED3',style: BorderStyle.Solid})}ListItem() {Row() {Text('退换货' + this.type).fontSize(13).fontColor('#222427')}.padding({left: 12,right: 12,top: 5,bottom: 5}).border({width: 1,radius: 4,color: '#C9CED3',style: BorderStyle.Solid})}ListItem() {Row() {Text('去支付' + this.type).fontSize(13).fontColor('#222427')}.padding({left: 12,right: 12,top: 5,bottom: 5}).border({width: 1,radius: 4,color: '#C9CED3',style: BorderStyle.Solid})}}.listDirection(Axis.Horizontal).scrollBar(BarState.Off).edgeEffect(EdgeEffect.None).width('100%')}.width('100%')}
}
3.2、实现效果
3.3、完成预期效果:按住按钮区域也能切换页签
解决方法:给list添加nestedScroll属性,解决嵌套组件的滚动问题
详细代码:
@Entry
@Component
struct TabsExample {@State fontColor: string = '#182431'@State selectedFontColor: string = '#007DFF'@State currentIndex: number = 0private controller: TabsController = new TabsController()@BuildertabBuilder(index: number, name: string) {Column() {Text(name).fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor).fontSize(16).fontWeight(this.currentIndex === index ? 500 : 400).lineHeight(22).margin({ top: 17, bottom: 7 })Divider().strokeWidth(2).color('#007DFF').opacity(this.currentIndex === index ? 1 : 0)}.width('100%')}build() {Column() {Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {TabContent() {OrderList({ type: '1' })}.tabBar(this.tabBuilder(0, 'green')).gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Right })))TabContent() {OrderList({ type: '2' })}.tabBar(this.tabBuilder(1, 'blue'))TabContent() {OrderList({ type: '3' })}.tabBar(this.tabBuilder(2, 'yellow'))TabContent() {OrderList({ type: '4' })}.tabBar(this.tabBuilder(3, 'pink')).gesture(PanGesture(new PanGestureOptions({ direction: PanDirection.Left })))}.vertical(false).barMode(BarMode.Fixed).barWidth(360).barHeight(56).animationDuration(400).onChange((index: number) => {this.currentIndex = index}).width(360).height(296).margin({ top: 52 }).backgroundColor('#F1F3F5')}.width('100%')}
}@Component
struct OrderList {@Prop type: stringbuild() {Column() {Column({ space: 30 }) {Row() {Text('文本' + this.type)}Row() {Text('文本' + this.type)}Row() {Text('文本' + this.type)}}.width('100%').height(150)List() {ListItem() {Row() {Text('取消订单' + this.type).fontSize(13).fontColor('#222427')}.padding({left: 12,right: 12,top: 5,bottom: 5}).border({width: 1,radius: 4,color: '#C9CED3',style: BorderStyle.Solid})}ListItem() {Row() {Text('查看发票' + this.type).fontSize(13).fontColor('#222427')}.padding({left: 12,right: 12,top: 5,bottom: 5}).border({width: 1,radius: 4,color: '#C9CED3',style: BorderStyle.Solid})}ListItem() {Row() {Text('申请发票' + this.type).fontSize(13).fontColor('#222427')}.padding({left: 12,right: 12,top: 5,bottom: 5}).border({width: 1,radius: 4,color: '#C9CED3',style: BorderStyle.Solid})}ListItem() {Row() {Text('退换货' + this.type).fontSize(13).fontColor('#222427')}.padding({left: 12,right: 12,top: 5,bottom: 5}).border({width: 1,radius: 4,color: '#C9CED3',style: BorderStyle.Solid})}ListItem() {Row() {Text('去支付' + this.type).fontSize(13).fontColor('#222427')}.padding({left: 12,right: 12,top: 5,bottom: 5}).border({width: 1,radius: 4,color: '#C9CED3',style: BorderStyle.Solid})}}.listDirection(Axis.Horizontal).scrollBar(BarState.Off).edgeEffect(EdgeEffect.None).width('100%').nestedScroll({scrollForward: NestedScrollMode.SELF_FIRST,scrollBackward: NestedScrollMode.SELF_FIRST})}.width('100%')}
}
四、nestedScroll介绍
nestedScroll:设置向前向后两个方向上的嵌套滚动模式,实现与父组件的滚动联动。
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
value | NestedScrollOptions | 是 | 嵌套滚动选项。 |
NestedScrollOptions对象说明
名称 | 类型 | 必填 | 描述 |
---|---|---|---|
scrollForward | NestedScrollMode | 是 | 滚动组件往末尾端滚动时的嵌套滚动选项。 |
scrollBackward | NestedScrollMode | 是 | 滚动组件往起始端滚动时的嵌套滚动选项。 |
NestedScrollMode枚举说明
名称 | 描述 |
---|---|
SELF_ONLY | 只自身滚动,不与父组件联动。 |
SELF_FIRST | 自身先滚动,自身滚动到边缘以后父组件滚动。父组件滚动到边缘以后,如果父组件有边缘效果,则父组件触发边缘效果,否则子组件触发边缘效果。 |
PARENT_FIRST | 父组件先滚动,父组件滚动到边缘以后自身滚动。自身滚动到边缘后,如果有边缘效果,会触发自身的边缘效果,否则触发父组件的边缘效果。 |
PARALLEL | 自身和父组件同时滚动,自身和父组件都到达边缘以后,如果自身有边缘效果,则自身触发边缘效果,否则父组件触发边缘效果。 |