HarmonyOS 鸿蒙Next 两个list使用scrolltoindex失效
HarmonyOS 鸿蒙Next 两个list使用scrolltoindex失效
两个list滑动,形成父子关系,共用一个二维数组,父list点击事件,触发两个scrollertoindex, 子组件更新,但是不会滑动,偶尔会划过去,有什么解决方案吗?
参考一下这个:
[@Entry](/user/Entry)
[@Component](/user/Component)
struct Page2 {
[@State](/user/State) messageArr: string[] = ['1', '2', '3', '4', '5', '6', '7']
scroller: Scroller = new Scroller()
[@State](/user/State) currentIndex: number = 1
scroller2: Scroller = new Scroller()
build() {
Column() {
List({ initialIndex: 1, scroller: this.scroller }) {
ListItem() {
Column() {
Text('second floor')
Button('to index 1').onClick(() => {
this.scroller.scrollToIndex(1, true, ScrollAlign.CENTER)
})
}
}
.height('100%')
.width('100%')
.backgroundColor(Color.Grey)
ListItem() {
Column() {
Row() {
Text('点击操作').onClick(() => {
this.scroller.scrollToIndex(0, true, ScrollAlign.CENTER)
this.scroller2.scrollToIndex(0, true, ScrollAlign.CENTER)
})
}
.height(100)
.width('100%')
.backgroundColor(Color.Pink)
List({ scroller: this.scroller2 }) {
ForEach(this.messageArr, (item: string) => {
ListItem() {
Row() {
Text(`message ${item}`)
}
.width('100%')
.height('200vp')
}
})
}
.divider({ strokeWidth: 2 })
.backgroundColor('#eee')
.nestedScroll({
scrollBackward: NestedScrollMode.SELF_FIRST,
scrollForward: NestedScrollMode.PARENT_FIRST,
})
.padding({
bottom: 100
})
.edgeEffect(EdgeEffect.None)
}
}
.width('100%')
.height('100%')
}
.friction(2)
.edgeEffect(EdgeEffect.None)
.scrollSnapAlign(ScrollSnapAlign.CENTER)
.onScrollFrameBegin((offset, state) => {
if (state === ScrollState.Fling) {
return { offsetRemain: 0 }
}
return { offsetRemain: offset }
})
.onScrollIndex((start, end, center) => {
this.currentIndex = center
})
.onTouch((event: TouchEvent) => {
let touchObject: TouchObject = event.touches[0]
if (touchObject.type === TouchType.Up) {
this.scroller.scrollToIndex(this.currentIndex, true, ScrollAlign.CENTER)
}
})
}
.height('100%')
.width('100%')
}
}
你看一下我给1楼发的代码,demo测试的时候是没问题的,但是实际上相同操作在工程代码上出现了问题,猜测是跳转发生在Ui更新完成前,导致无法跳转,想找一下解决方案,我试用settimeout100 可以解决,但是项目好像不支持这个时间
期待HarmonyOS能在未来带来更多创新的技术和理念。
import { promptAction } from ‘@kit.ArkUI’;
export class parent { title: string = ‘’ child: child[] = [] selectId: number = 0 }
export class child { title: string = ‘’ image: ResourceStr = ‘’ }
@Entry @Component struct TabsOpaque { @State tabArray: parent[] = [{ title: ‘父0’, child: [{ title: ‘子0’, image: $r(‘app.media.app_icon’) }], selectId: 0 }, { title: ‘父1’, child: [{ title: ‘子0’, image: $r(‘app.media.app_icon’) }, { title: ‘子1’, image: $r(‘app.media.app_icon’) }, { title: ‘子2’, image: $r(‘app.media.app_icon’) }, { title: ‘子3’, image: $r(‘app.media.app_icon’) }, { title: ‘子4’, image: $r(‘app.media.app_icon’) }], selectId: 3 }, { title: ‘父2’, child: [{ title: ‘子0’, image: $r(‘app.media.app_icon’) }, { title: ‘子0’, image: $r(‘app.media.app_icon’) }], selectId: 0
}, { title: ‘父3’, child: [{ title: ‘子0’, image: $r(‘app.media.app_icon’) }, { title: ‘子0’, image: $r(‘app.media.app_icon’) }], selectId: 0 }] @State contCurrentIndex: number = 0; //记录当前内容导航索引 @State subCurrentIndex: number = 0; //记录当前下部导航索引 selectedFontColor: Color = Color.Black fontColor: Color = Color.Blue //滑动X轴 @State offsetX: number = 0 private subController: Scroller = new Scroller() private subListController: Scroller = new Scroller() private contScroller: Scroller = new Scroller() private contListScroller: Scroller = new Scroller()
build() { Column() { //用于窗口晃动操作 Column() { Text(‘用于滑动驱动变化’) .onClick(() => { this.contCurrentIndex++ this.contListScroller.scrollToIndex(this.contCurrentIndex, true, ScrollAlign.CENTER) }) } .justifyContent(FlexAlign.Center) .align(Alignment.Center) .height(“50%”) .width(“100%”) .gesture( PanGesture() .onActionUpdate((event: GestureEvent) => { if (event) { this.offsetX = this.offsetX + event.offsetX } }) .onActionEnd((event: GestureEvent) => { //极端return if (this.contCurrentIndex == 0 && this.subCurrentIndex == 0 && this.offsetX > 0) { this.offsetX = 0 return } if (this.contCurrentIndex == this.tabArray[this.subCurrentIndex].child.length - 1 && this.subCurrentIndex == this.tabArray.length - 1 && this.offsetX < 0) { this.offsetX = 0 return } //右滑 if (this.offsetX > 0) { if (this.contCurrentIndex == 0) { this.subCurrentIndex– this.subListController.scrollToIndex(this.subCurrentIndex, true, ScrollAlign.CENTER) } else { this.contCurrentIndex– this.contListScroller.scrollToIndex(this.contCurrentIndex, true, ScrollAlign.CENTER) } } //左滑 if (this.offsetX < 0) { if (this.contCurrentIndex == this.tabArray[this.subCurrentIndex].child.length - 1) { this.subCurrentIndex++ this.subListController.scrollToIndex(this.subCurrentIndex, true, ScrollAlign.CENTER) } else { this.contCurrentIndex++ this.contListScroller.scrollToIndex(this.contCurrentIndex, true, ScrollAlign.CENTER) } } this.offsetX = 0 //更新为0 }) )
//子Tab
Scroll(this.contScroller) {
List({ scroller: this.contListScroller }) {
ForEach(this.tabArray[this.subCurrentIndex].child, (contTab: child, contIndex: number) => {
ListItem() {
Column() {
Image($r('app.media.app_icon'))
.width(20)
Text(contTab.title)
.fontSize(20)
.fontColor(this.contCurrentIndex == contIndex ? Color.Red : Color.Black)
.onClick(() => {
this.contListScroller.scrollToIndex(contIndex, true, ScrollAlign.CENTER)
this.contCurrentIndex = contIndex
})
}
.margin({
left: 10,
right: 10
})
}
})
}
.gesture(
PanGesture()
.onActionStart((event: GestureEvent) => {
if (event) {
//极限返回
if ((this.contCurrentIndex == 0 && event.offsetX > 0) ||
(this.contCurrentIndex == this.tabArray[this.subCurrentIndex].child.length - 1 &&
event.offsetX < 0)) {
return
}
//触发滑动
if (event.offsetX < 0) {
this.contCurrentIndex++
} else {
this.contCurrentIndex--
}
this.contListScroller.scrollToIndex(this.contCurrentIndex, true, ScrollAlign.CENTER)
}
})
)
.enableScrollInteraction(false) //关闭自带滑动
.scrollSnapAlign(ScrollSnapAlign.CENTER)
.width("100%")
.height("100%")
.listDirection(Axis.Horizontal)
.scrollBar(BarState.Off)
}
.width("100%")
.height(50)
.border({
width: 1
})
.scrollBar(BarState.Off)
.scrollable(ScrollDirection.Horizontal)
//父
Scroll(this.subController) {
List({ scroller: this.subListController }) {
ForEach(this.tabArray, (subTab: parent, subIndex: number) => {
ListItem() {
Text(subTab.title)
.fontSize(30)
.fontColor(this.subCurrentIndex == subIndex ? Color.Red : Color.Black)
.onClick(async () => {
//TODO 未更新二级滑动 使用scrollToIndex 出现index>子组件最大索引 取消跳转
if (this.subCurrentIndex == subIndex) {
return
}
await this.subListController.scrollToIndex(subIndex, true, ScrollAlign.CENTER)
this.subCurrentIndex = subIndex
// 更新子导航索引 视图更新
this.contCurrentIndex = this.tabArray[subIndex].selectId
await this.contListScroller.scrollToIndex(this.contCurrentIndex, true, ScrollAlign.CENTER)
})
.margin({
left: 10,
right: 10
})
}
})
}
.gesture(
PanGesture()
.onActionStart((event: GestureEvent) => {
if (event) {
//极限返回
if ((this.subCurrentIndex == 0 && event.offsetX > 0) ||
(this.subCurrentIndex == this.tabArray.length - 1 && event.offsetX < 0)) {
return
}
//触发滑动
if (event.offsetX < 0) {
this.subCurrentIndex++
} else {
this.subCurrentIndex--
}
this.subListController.scrollToIndex(this.subCurrentIndex, true, ScrollAlign.CENTER)
}
// Event.offsetX>0
})
)
.enableScrollInteraction(false) //关闭自带滑动
.scrollSnapAlign(ScrollSnapAlign.CENTER)
.scrollBar(BarState.Off)
.listDirection(Axis.Horizontal)
.width("100%")
.height(30)
}
.scrollBar(BarState.Off)
.scrollable(ScrollDirection.Horizontal)
}
} }
demo 和代码有一些出入,不知道是数组嵌套原因,还是哪里出现问题,我在第二个控制器跳转前加了settimeout 100 就避免了这个问题发生,我猜测是UI更新,父改变索引,趋势子视图发生变化,而第二个控制器跳转应该是发生在完全更新之前,形成了【未更新二级滑动 使用scrollToIndex 出现index>子组件最大索引 取消跳转】,且监听ScrollStart 未发生, 有没有什么办法监听子组件更新成功后在进行后续操作的方案?
demo没问题,和延迟有关。可以从几个方面入手 【1】数据更新过程尽量不要删减组件,只改变组件内容的情况下通常没有问题。 【2】尝试使用@Watch装饰器监听,在监听回调里处理你的操作方法 【3】我看到你用了async ,建议这里使用EventHub发送到主线程去执行更新UI操作 【4】现在你这种数据更新方式落后了,建议使用@ObservedV2+@Trace 参考:https://blog.csdn.net/zhongcongxu01/article/details/142677808
针对HarmonyOS 鸿蒙Next中两个list使用scrollToIndex失效的问题,可能的原因及解决方案如下:
-
高度设置不当:
- List组件未设置高度或高度设置不合理,会导致无法正常渲染和计算布局,从而影响scrollToIndex功能。
- 解决方案:确保每个List组件都有合理且固定的高度设置。
-
嵌套Scroll容器:
- 如果List组件嵌套在Scroll容器中,且Scroll容器未设置固定高度,会导致滚动事件处理异常。
- 解决方案:为嵌套的Scroll容器设置固定高度,确保滚动事件正常触发。
-
数据加载与渲染问题:
- 动态加载数据时,若数据加载未完成或渲染逻辑存在性能瓶颈,也可能影响scrollToIndex的效果。
- 解决方案:确保数据加载完成后再调用scrollToIndex,并优化数据渲染逻辑。
-
版本或系统问题:
- 某些HarmonyOS版本可能存在特定bug,影响scrollToIndex功能。
- 解决方案:尝试更新HarmonyOS版本到最新,看问题是否得到解决。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html 。