鸿蒙HarmonyOS tabs左右滑动,tabbar文字渐变效果

91 阅读1分钟
import { TabBarView } from "../components/TabBarView"

export enum ListBarState{
  START,STOP,DRAG
}
@Entry
@Component
export struct TabBarGradientPage {
  private swiperController: SwiperController = new SwiperController()
  @State currentIndex: number = 0
  @State nextIndex: number = 0
  @State ratio: number = 0.3
  @State barState:ListBarState =ListBarState.START
  private tabsWidth: number = 0;
  @State arr: string[] = ['关注', '推荐', '热点', '上海', '视频', '新时代', '新歌', '新碟', '新片'];

  build() {
    Column() {
      TabBarView({
        listData: this.arr,
        currentIndex: this.currentIndex,
        nextIndex: this.nextIndex,
        ratio: this.ratio,
        barState:this.barState
      })

      Swiper(this.swiperController) {
        ForEach(this.arr, (item:string) => {
          Text(item).width('100%').height('100%').textAlign(TextAlign.Center)
        }, (item: string) => item)
      }
      .loop(false)
      .onChange((index: number) => {
        this.currentIndex = index; // 监听索引index的变化,实现页签内容的切换。
      })
      .onAreaChange((_oldValue: Area, newValue: Area) => {
        this.tabsWidth = newValue.width as number;
      })
      .onAnimationStart((_index: number, targetIndex: number) => {
        this.currentIndex = targetIndex;
        this.barState =ListBarState.START
      })
      .onAnimationEnd((index: number, event: TabsAnimationEvent) => {
        this.barState =ListBarState.STOP
      })
      .onGestureSwipe((index: number, event: TabsAnimationEvent) => {
        this.barState =ListBarState.DRAG
        // 在页面跟手滑动过程中,逐帧触发该回调。
        let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event);
        this.currentIndex = currentIndicatorInfo.index;
      })
    }.width('100%').height('100%')
  }

  private getCurrentIndicatorInfo(index: number, event: TabsAnimationEvent): Record<string, number> {
    let nextIndex = this.currentIndex;
    if (index > 0 && event.currentOffset > 0) {
      nextIndex--;
    } else if (index < this.arr.length - 1 && event.currentOffset < 0) {
      nextIndex++;
    }
    this.nextIndex = nextIndex
    let swipeRatio = Math.abs(event.currentOffset / (this.tabsWidth/2));
    swipeRatio = swipeRatio > 1 ? 1 : swipeRatio < 0.3 ? 0.3 : swipeRatio
    if (this.nextIndex==this.currentIndex) {
      swipeRatio=1
    }
    this.ratio=swipeRatio
    let currentIndex = swipeRatio > 1 ? nextIndex : index; // 页面滑动超过一半,tabBar切换到下一页。
    return { 'index': currentIndex };
  }

}
import { ListBarState } from "../pages/TabBarGradientPage"

@Component
export struct TabBarView {
  private listScroller: Scroller = new Scroller()
  @Prop listData:  string[]
  @Prop   @Watch('currentIndexChange') currentIndex: number
  @Prop nextIndex: number
  @Prop ratio: number
  @Prop barState: ListBarState

  currentIndexChange(){
   this.listScroller.scrollToIndex(this.currentIndex,true,ScrollAlign.CENTER)
  }

  build() {
    List({ scroller: this.listScroller }) {
      ForEach(this.listData, (item: string, index: number) => {
        ListItem() {
          Text(item)
            .fontWeight(this.currentIndex == index ? FontWeight.Bold : FontWeight.Regular)
            .fontSize(this.currentIndex == index ? 20 : 16)
            .fontColor(Color.Black)
            .padding(10)
            .width(100)
            .height('100%')
            .opacity(this.getTextOp(index))
            .borderWidth(1)
            .borderColor(Color.Red)
            .textAlign(TextAlign.Center)
        }
      }, (item: string, index: number) => JSON.stringify(item) + index)
    }.width('100%').height(60).listDirection(Axis.Horizontal).scrollBar(BarState.Off)
  }

  getTextOp(indxe: number) {
    if (this.barState === ListBarState.DRAG) {
      if (this.nextIndex === indxe) {
        return this.ratio
      }
    }
    return this.currentIndex === indxe ? 1 : 0.3
  }
}