DEV Community

HarmonyOS
HarmonyOS

Posted on

How to display only the corresponding TabContent page?

Read the original article:How to display only the corresponding TabContent page?

How to display only the corresponding TabContent page?

Problem Description

In the Tabs component, since it comes with a built-in sliding animation for switching between pages, when you click on a tab bar to switch pages, the current page will slide to the target page. This causes the intermediate pages between the current and target pages to be loaded as well.

Background Knowledge

LazyForEach must be used within container components. Only the List, ListItemGroup, Grid, Swiper, and WaterFlow components support lazy data loading. Other components still load all data at once. Refer to the usage restrictions for details.

To customize the animation for tab page switching, refer to the usage of customContentTransition.

Solution

Option 1: Since the Tabs component comes with a built-in sliding transition animation for page switching, when you click on a tab bar to switch pages, the current page will slide to the target page, causing intermediate pages between the current and target pages to be loaded as well. You can use custom transition animations to avoid the default animation provided by the Tabs component. Refer to the customContentTransition usage instructions.

Example code is as follows:

@Entry
@Component
struct TabsDemo {
  @State currentIndex: number = 0
  private tabsController: TabsController = new TabsController()
  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(296)
      .onChange((index: number) => {
        this.currentIndex = index
      })
    }
  }
}

@Component
struct MyComponent {
  private color: string = ""

  aboutToAppear(): void {
    console.info('------aboutToAppear backgroundColor:' + this.color)
  }

  aboutToDisappear(): void {
    console.info('------aboutToDisappear backgroundColor:' + this.color)
  }

  build() {
    Column() {
      Text(this.color)
        .width('90%')
        .height(200)
        .borderRadius(10)
        .backgroundColor($r('sys.color.comp_background_focus'))
        .textAlign(TextAlign.Center)
        .fontSize(30)
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The run log is as follows, which can prevent intermediate tabs from being loaded:

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
Enter fullscreen mode Exit fullscreen mode

Option 2 : To avoid loading intermediate pages while retaining the swipe gesture for switching between pages, you can use Swiper to customize the Tabs component. By calling the changeIndex method of SwiperController to navigate to a specified page, you can set useAnimation to false to disable animations.

Example code is 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(160)
            .borderRadius(10)
            .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)
      Row({ 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)
    }.width('100%')
    .margin({ top: 5 })
  }
}
Enter fullscreen mode Exit fullscreen mode

Verification Result

After disabling the default tab sliding animation using customContentTransition or replacing Tabs with a Swiper and setting useAnimation to false, only the corresponding TabContent page is displayed and loaded, and intermediate pages are no longer created or rendered during tab switching.

Written by Mehmet Karaaslan

Top comments (0)