Read the original article:How to Display Only the Content Page Corresponding to the Tab
How to Display Only the Content Page Corresponding to the Tab
Context
In the Tabs component, due to the built-in sliding animation for page switching, when clicking on the tabBar to switch pages, the transition slides from the current page to the target page. This causes the intermediate pages between the current and target pages to also be loaded.
Description
In the Tabs component, due to the built-in sliding animation for page switching, clicking the tabBar to switch pages results in sliding from the current page to the target page, which causes the intermediate pages between the current and target pages to be loaded as well.
-
LazyForEachmust be used within container components. OnlyList,ListItemGroup,Grid,Swiper, andWaterFlowcomponents support lazy data loading. Other components still load all data at once. Refer to Usage Restrictions. - Custom Tabs page transition animation, refer to customContentTransition.
Solution
Solution 1:
Since the Tabs component has a built-in sliding animation for page switching, clicking the tabBar to switch pages causes a slide from the current page to the target page, resulting in the loading of intermediate pages. This can be avoided by using a custom transition animation. Refer to the customContentTransition usage instructions.
Sample code as follows:
@Entry
@Component
struct TabsDemo {
@State currentIndex: number = 0
private tabsController: TabsController = new TabsController()
// Set page transition animations to replace the swipe-to-navigate page transition animations.
private customContentTransition: (from: number, to: number) => TabContentAnimatedTransition =
(from: number, to: number) => {
let tabContentAnimatedTransition = {
timeout: 1000,
transition: (proxy: TabContentTransitionProxy) => {
this.getUIContext().animateTo({
duration: 0,
onFinish: () => {
proxy.finishTransition()
}
}, () => {
})
}
} as TabContentAnimatedTransition
return tabContentAnimatedTransition
}
build() {
Column() {
Tabs({ index: this.currentIndex, controller: this.tabsController }) {
TabContent() {
MyComponent({ color: '#00CB87' })
}.tabBar(SubTabBarStyle.of('green'))
TabContent() {
MyComponent({ color: '#007DFF' })
}.tabBar(SubTabBarStyle.of('blue'))
TabContent() {
MyComponent({ color: '#FFBF00' })
}.tabBar(SubTabBarStyle.of('yellow'))
TabContent() {
MyComponent({ color: '#E67C92' })
}.tabBar(SubTabBarStyle.of('pink'))
}
.customContentTransition(this.customContentTransition)
.width('100%')
.height('100%')
.onChange((index: number) => {
this.currentIndex = index
})
}
.backgroundColor(Color.White)
.padding(10)
}
}
@Component
struct MyComponent {
@Prop color: string = ""
aboutToAppear(): void {
console.info('------aboutToAppear backgroundColor:' + this.color) // By reviewing the log output,
// it can be observed that the intermediate page was not loaded.
}
aboutToDisappear(): void {
console.info('------aboutToDisappear backgroundColor:' + this.color)
}
build() {
Column() {
Text(this.color)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.fontSize(30)
}
.borderRadius(10)
.width('90%')
.height('90%')
.justifyContent(FlexAlign.Center)
.backgroundColor(this.color)
}
}
Runtime log as follows, which avoids loading the intermediate tabs:
08-13 10:25:53.034 22832-22832 A03d00/JSAPP com.example.ir_test I ------aboutToAppear backgroundColor:#00CB87
08-13 10:26:04.021 22832-22832 A03d00/JSAPP com.example.ir_test I ------aboutToAppear backgroundColor:#E67C92
08-13 10:26:05.250 22832-22832 A03d00/JSAPP com.example.ir_test I ------aboutToAppear backgroundColor:#FFBF00
Solution 2:
To both avoid loading intermediate pages and retain the gesture-based swipe functionality for page switching, you can use a Swiper to custom-implement the Tabs component. By calling the changeIndex method of SwiperController, you can switch to a specific page. When useAnimation is set to false, there is no animation effect.
Sample code as follows:
class MyDataSource implements IDataSource {
private list: number[] = []
constructor(list: number[]) {
this.list = list
}
totalCount(): number {
return this.list.length
}
getData(index: number): number {
return this.list[index]
}
registerDataChangeListener(listener: DataChangeListener): void {
}
unregisterDataChangeListener() {
}
}
@Entry
@Component
struct SwiperExample {
private swiperController: SwiperController = new SwiperController()
private data: MyDataSource = new MyDataSource([])
aboutToAppear(): void {
let list: number[] = []
for (let i = 1; i <= 10; i++) {
list.push(i);
}
this.data = new MyDataSource(list)
}
build() {
Column({ space: 5 }) {
Swiper(this.swiperController) {
LazyForEach(this.data, (item: string) => {
Text(item.toString())
.width('90%')
.height('50%')
.borderRadius(10)
.fontColor(Color.Black)
.backgroundColor($r('sys.color.comp_background_focus'))
.textAlign(TextAlign.Center)
.fontSize(30)
}, (item: string) => item)
}
.cachedCount(2)
.index(1)
.autoPlay(true)
.interval(4000)
.loop(true)
.duration(1000)
.itemSpace(0)
.indicator(false)
Column({ space: 12 }) {
Button('change to index:4')
.onClick(() => {
this.swiperController.changeIndex(3,false)
})
Button('change to index:7')
.onClick(() => {
this.swiperController.changeIndex(6,false)
})
}.margin(5)
}
.height('100%')
.width('100%')
.margin({ top: 5 })
}
}
Key Takeaways
- The default sliding animation in Tabs can cause unwanted loading of intermediate pages.
- Using
customContentTransitioncan override the default animation and prevent intermediate page loading. - Implementing Tabs using
Swiperprovides more control, including disabling animation while preserving swipe gestures.
Reference Links
- Usage Restrictions for Lazy Loading
- Custom Content Transition in Tabs
- Swiper Change Index and Animation Contro
Top comments (0)