HarmonyOS 鸿蒙Next tab嵌套横向list实现自动滑动切换
HarmonyOS 鸿蒙Next tab嵌套横向list实现自动滑动切换
可以参考以下代码实现list滑动到最右边就自动触发tab的滑动切换:
import { router } from '@kit.ArkUI'
export struct Tabs240529160413047 {
@State tabArray: Array<number> = [0, 1, 2, 3, 4, 5, 6, 7]
@State focusIndex: number = 0
@State pre: number = 0
@State index: number = 0
private controller: TabsController = new TabsController()
@State test: boolean = false
@State animationDuration: number = 300
@State indicatorLeftMargin: number = 0
@State indicatorWidth: number = 0
private tabWidth: number = 0;
private scrollerForScroll: Scroller = new Scroller()
// 单独的页签
Tab(tabName: string, tabItem: number, tabIndex: number) {
Row({ space: 20 }) {
Text(tabName)
.fontSize(18)
.fontColor(tabIndex === this.focusIndex ? Color.Blue : Color.Black)
.id(tabIndex.toString())
.onAreaChange((oldValue: Area, newValue: Area) => {
if (this.focusIndex === tabIndex && (this.indicatorLeftMargin === 0 || this.indicatorWidth === 0)) {
if (newValue.position.x != undefined) {
let positionX = Number.parseFloat(newValue.position.x.toString())
this.indicatorLeftMargin = Number.isNaN(positionX) ? 0 : positionX
}
let width = Number.parseFloat(newValue.width.toString())
this.tabWidth = Number.isNaN(width) ? 0 : width
this.indicatorWidth = this.tabWidth
}
})
}
.justifyContent(FlexAlign.Center)
.constraintSize({ minWidth: 35 })
.width(120)
.height(30)
.onClick(() => {
this.controller.changeIndex(tabIndex)
this.focusIndex = tabIndex
})
.backgroundColor("#ffb7b7b7")
}
WebTab(tabName: string, tabItem: number, tabIndex: number) {
Row({ space: 20 }) {
Text(tabName).fontSize(18).fontColor(tabIndex === this.focusIndex ? Color.Blue : Color.Black)
}
.justifyContent(FlexAlign.Center)
.constraintSize({ minWidth: 35 })
.width(120)
.height(30)
.onClick(() => {
router.pushUrl({ url: ‘pages/WebPage’ })
})
.backgroundColor("#ffb7b7b7")
}
build() {
Column() {
Stack({ alignContent: Alignment.TopStart }) {
Row() { // 页签
List({ space: 0, initialIndex: 0, scroller: this.scrollerForScroll }) {
ForEach(this.tabArray, (item: number, index: number) => {
if (item == 4) {
ListItem() {
this.WebTab("页签 " + item, item, index)
}
} else {
ListItem() {
this.Tab("页签 " + item, item, index)
}
}
}, (item: string) => item)
}
.listDirection(Axis.Horizontal)
.height(30)
.friction(0.6)
.alignListItem(ListItemAlign.Start)
.scrollBar(BarState.Off)
.width(‘100%’)
.backgroundColor("#ffb7b7b7")
.onScroll((xOffset: number, yOffset: number) => {
this.indicatorLeftMargin -= xOffset
})
}.width(‘100%’)
Column()
.height(2)
.width(this.indicatorWidth)
.margin({ left: this.indicatorLeftMargin, top: 30 })
.backgroundColor(Color.Blue)
}
.height(40)
.width(‘100%’)
.backgroundColor("#ffb7b7b7") //tabs
Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
ForEach(this.tabArray, (item: number, index: number) => {
TabContent() {
Text('我是页面 ’ + item + " 的内容").height(300).width(‘100%’).fontSize(30)
}.backgroundColor(Color.White)
}, (item: string) => item)
}.width(‘100%’).barHeight(0).animationDuration(0).onChange((index: number) => {
console.log(‘foo change’)
this.focusIndex = index
this.scrollerForScroll.scrollToIndex(index - 1, true)
let indexInfo = this.getTextInfo(index)
let currentLeft = indexInfo.left
let currentWidth = indexInfo.width
this.startAnimateTo(20, currentLeft, currentWidth)
})
}.width(‘100%’).height(‘100%’)
}
private getTextInfo(index: number): Record<string, number> {
let strJson = getInspectorByKey(index.toString())
try {
let obj: Record<string, string> = JSON.parse(strJson)
let rectInfo: number[][] = JSON.parse(’[’ + obj.$rect + ‘]’)
return { ‘left’: px2vp(rectInfo[0][0]), ‘width’: px2vp(rectInfo[1][0] - rectInfo[0][0]) }
} catch (error) {
return { ‘left’: 0, ‘width’: 0 }
}
}
private startAnimateTo(duration: number, leftMargin: number, width: number) {
animateTo({
duration: duration, // 动画时长
curve: Curve.Linear, // 动画曲线
iterations: 1, // 播放次数
playMode: PlayMode.Normal, // 动画模式
onFinish: () => {
console.info(‘play end’)
}
}, () => {
this.indicatorLeftMargin = leftMargin
this.tabWidth = width
this.indicatorWidth = width
})
}
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
更多关于HarmonyOS 鸿蒙Next tab嵌套横向list实现自动滑动切换的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
[@Entry](/user/Entry)
[@ComponentV2](/user/ComponentV2)
struct Index {
build() {
Tabs() {
TabContent() {
Column() {
}.size({ width: '100%', height: '100%' })
.backgroundColor(Color.Green)
}
TabContent() {
List() {
ListItem() {
Text('3').width('40%').backgroundColor(Color.Gray)
}
ListItem() {
Text('3').width('40%').backgroundColor(Color.Orange)
}
ListItem() {
Text('2').width('40%').backgroundColor(Color.Gray)
}
ListItem() {
Text('1').width('40%').backgroundColor(Color.Blue)
}
}.width('100%')
.listDirection(Axis.Horizontal)
.nestedScroll({
scrollForward: NestedScrollMode.SELF_FIRST,
scrollBackward: NestedScrollMode.SELF_FIRST,
})
}
TabContent() {
Column() {
}.size({ width: '100%', height: '100%' })
.backgroundColor(Color.Gray)
}
}.size({ width: '100%', height: '100%' })
}
}
list nestedScroll 嵌套滑动设定优先滑动自己。然后其余的系统会处理好