鸿蒙Swiper替代Tabs初探

3 篇文章 0 订阅
3 篇文章 0 订阅

鸿蒙目前tabs组件tabContent+tabBar 能够使用的api有点差,太难用了,示例如下:

      Tabs({ barPosition: BarPosition.Start ,index: this.currentTabIndex}) {
        LazyForEach(this.homeTabData, (tabData: TabData, index: number) => {
          TabContent() {
            if (tabData.type == 'edu_plan') {
              EduPlanFrag({ tabData: tabData, fragIndex: index })
            } else if (tabData.type == 'edu_history') {
              PersonCenterFrag({ tabData: tabData, fragIndex: index })
            } else {
              ComWaterfallFrag({ tabData: tabData, fragIndex: index })
            }
          }
          .tabBar(this.tabBuilder(tabData, index))//tabBar只能接受builder或者直接写组件
        }, (tabData: TabData) => tabData.type)
      }
      //这里可以触发,但是tabContent和tabBar里面的组件都无法触发焦点事件
      .onFocus(()=>{
        this.isFocused = true
      })
      .onBlur(()=>{
        this.isFocused = false
      })
      .barWidth('auto')
      .barHeight('28vp')
      .width('auto')
      .barMode(BarMode.Scrollable)
      .scrollable(false)
      .animationDuration(50)
      .onChange((index: number) => {
        this.currentTabIndex = index
        this.onTabChange(index)
      })
      
  		@Builder tabBuilder(tabData: TabData,index:number) {
    		TabItem({tabData: tabData, setTabIndex: index})
  		}


@Component
export struct TabItem {

  setTabIndex: number = 0
  tabData: TabData
  @Consume currentTabIndex: number
  @State isFocused: boolean = false
  onFocusChange? : (index)=>void

  build() {
    Row() {
      Text(this.tabData.name).fontSize(14)
        .fontColor(this.isFocused && this.setTabIndex == this.currentTabIndex ? $r('app.color.white_100') :
          (this.setTabIndex == this.currentTabIndex ? $r('app.color.btn_select_color') : $r('app.color.white_70')))
        .padding({ left: 12, right: 12 })
        .focusable(true)
    }
    .onFocus(()=>{
      this.isFocused = true
      this.onFocusChange(this.setTabIndex)
    })
    .onBlur(()=>{
      this.isFocused = false
    })
    .defaultFocus(this.setTabIndex == this.currentTabIndex)
    .borderRadius(14)
    .borderWidth(0)
    .borderColor($r('app.color.transparent'))
    .width('auto')
    .height(28)
    .backgroundColor(this.isFocused && this.setTabIndex == this.currentTabIndex ? $r('app.color.white_100') : $r('app.color.transparent'))
  }
}

上面的写法看似没有问题,其实是不行的,TabContent() {}.tabBar() 这个结构是一体的,当中的所有元素都没法监听到onFocus和onBlur, 导致tabItem 没法实现选中效果,只能设置获焦效果,而且而且,tabBar是水平居中的,怎么设都没用

可以通过swiper替代实现类似的效果:

@Component
export struct HomeTabsLayout {

  homeTabData: HomeTabData
  onTabChange? : (index: number) => void

  @Provide isFocused: boolean = false
  @Consume currentTabIndex: number

  swiperControl: SwiperController = new SwiperController()

  build() {
    Column() {
      Row() {
        LazyForEach(this.homeTabData, (tabData: TabData, index: number) => {
          TabItem({tabData: tabData, setTabIndex: index, onFocusChange:(changeIndex)=>{
            if (this.currentTabIndex != changeIndex) {
            	//这里需要先触发一下swiper的onChange
              this.onFocusScroll(this.currentTabIndex, changeIndex)
            }
          }})
        }, (tabData: TabData) => tabData.type)
      }

      Swiper(this.swiperControl) {
        ForEach(this.homeTabData.items, (tabData: TabData, index: number) => {
          ComWaterfallFrag({ tabData: tabData, fragIndex: index })
        }, (tabData: TabData) => tabData.type)
      }.index(this.currentTabIndex)
      .autoPlay(false)
      .indicator(false)
      .loop(false)
      .width('100%')
      .height('100%')
      .displayMode(SwiperDisplayMode.Stretch)
      .cachedCount(3)
      .disableSwipe(true)
      .duration(50)
      .onChange((swiperIndex)=>{
        if (this.currentTabIndex != swiperIndex) {
          this.scrollOneFrag(swiperIndex,this.currentTabIndex)
        }
      })
    }.width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Start)
  }

  onFocusScroll(from: number, to: number) {
    this.currentTabIndex = to
    this.scrollOneFrag(from,to)
  }

  scrollOneFrag(from:number,to:number) {
    Logger.i(TAG,"==scrollOneFrag==from:"+from + " ,to:" + to)
    if (from > to) {
      this.swiperControl.showPrevious()
    } else if (from < to){
      this.swiperControl.showNext()
    }
  }

  @Builder tabBuilder(tabData: TabData,index:number) {
    TabItem({tabData: tabData, setTabIndex: index})
  }
}

这个也可以实现类似于tab+tabcontent的效果,而且更加灵活好设计

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值