HarmonyOS 折叠吸顶

HarmonyOS
2天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
aquaa
@Entry
@Component
struct Index {
  @State tabArray: Array<number> = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  @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 tabsWidth: number = 0
  private tabWidth: number = 0;
  private scrollerForScroll: Scroller = new Scroller()

  searchSwiper: string[] = [
    "XXXXXX xs2",
    "XX20 Plus",
    "XXXXBook 13",
    "XXXX7 Pro"
  ]

  // 单独的页签
  @Builder
  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(100)
    .height(30)
    .onClick(() => {
      this.controller.changeIndex(tabIndex)
      this.focusIndex = tabIndex
    })
    .backgroundColor("#ffb7b7b7")
  }

  @Builder
  textTest(textName: string) {
    Row({ space: 20 }) {
      Text(textName)
        .fontSize(18)
        .onClick(() => {

        })
    }.justifyContent(FlexAlign.Center)
    .constraintSize({ minWidth: 35 })
    .height(30)
    .backgroundColor("#ffb7b7b7")
  }


  build() {
    Column() {
      // 滚动输入框
      Row() {
        Swiper() {
          ForEach(this.searchSwiper, (item: string) => {
            Column() {
              Text(item)
                .fontSize('14fp')
                .fontColor(Color.Black)
            }
            .alignItems(HorizontalAlign.Start)
          }, (item: string) => JSON.stringify(item))
        }
        .autoPlay(true)
        .loop(true)
        .vertical(true)
        .indicator(false)
      }
      .height('40vp')
      .width('100%')
      .borderRadius('20vp')
      .backgroundColor(Color.Pink)
      .padding({top: '12vp', bottom: '12vp'})

      Scroll() {
        Column() {
          Row() {
            Text("四个入口")
          }.height(100)
          .width("100%")
          .backgroundColor(Color.Orange)
          .margin({ top: '10vp', bottom: '10vp' })

          // 页签栏
          Stack({ alignContent: Alignment.TopStart }) {
            Column() {
              // 页签
              Row({ space: 8 }) {
                List({ space: 20, initialIndex: 0, scroller: this.scrollerForScroll }) {
                  ForEach(this.tabArray, (item: number, index: number) => {
                    ListItem() {
                      this.Tab("页签 " + item, item, index)
                    }
                  }, (item: string) => item)
                }
                .listDirection(Axis.Horizontal)
                .height(30)
                .width('80%')
                .friction(0.6)
                .alignListItem(ListItemAlign.Start)
                .scrollBar(BarState.Off)
                .width('80%')
                .backgroundColor("#ffb7b7b7")
                .onScroll((xOffset: number, yOffset: number) => {
                  this.indicatorLeftMargin -= xOffset
                })

                this.textTest('更多')
              }
              .alignItems(VerticalAlign.Bottom)
              .width('100%')
              .backgroundColor("#ffb7b7b7")
            }
            .alignItems(HorizontalAlign.Start)
            .width('100%')

            Column()
              .height(2)
              .width(this.indicatorWidth)
              .margin({ left: this.indicatorLeftMargin, top: 30 })
              .backgroundColor(Color.Green)
            Column().height(10).width("20%").margin({ left: '80%', top: 28 }).backgroundColor("#ffb7b7b7")
          }
          .height(40)
          .width('100%')
          .backgroundColor("#ffb7b7b7")
           
          //tabs
          Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
            ForEach(this.tabArray, (item: number, index: number) => {
              TabContent() {
                List({ space: 5, initialIndex: 0 }) {
                  ForEach(this.tabArray, (itemInfo: number) => {
                    ListItem() {
                      Text('我是页面 ' + item + " 的内容: " + itemInfo)
                        .height(150)
                        .width('100%')
                        .fontSize(30)
                        .backgroundColor(Color.Brown)
                    }
                  }, (item: string) => item)
                }.nestedScroll({
                  scrollForward: NestedScrollMode.PARENT_FIRST,
                  scrollBackward: NestedScrollMode.SELF_FIRST
                })
                .scrollBar(BarState.Off)
                .listDirection(Axis.Vertical)
                .friction(0.9)
                .edgeEffect(EdgeEffect.None)
              }.backgroundColor(Color.White)
            }, (item: string) => item)
          }
          .onAreaChange((oldValue: Area, newValue: Area) => {
            let width = Number.parseFloat(newValue.width.toString())
            this.tabsWidth = Number.isNaN(width) ? 0 : width
          })
          .width('100%')
          .barHeight(0)
          .height("calc(100% - 40vp)")
          .animationDuration(100)
          .onChange((index: number) => {
            console.log('foo change')
            this.focusIndex = index
            this.scrollerForScroll.scrollToIndex(index - 1, true)
          })
          .onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
            // 切换动画开始时触发该回调。下划线跟着页面一起滑动
            this.focusIndex = targetIndex
            let targetIndexInfo = this.getTextInfo(targetIndex)
            this.startAnimateTo(this.animationDuration, targetIndexInfo.left, targetIndexInfo.width)
          })
          .onAnimationEnd((index: number, event: TabsAnimationEvent) => {
            // 切换动画结束时触发该回调。下划线动画停止。
            let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event)
            this.startAnimateTo(0, currentIndicatorInfo.left, currentIndicatorInfo.width)
          })
          .onGestureSwipe((index: number, event: TabsAnimationEvent) => {
            // 在页面跟手滑动过程中,逐帧触发该回调。
            let currentIndicatorInfo = this.getCurrentIndicatorInfo(index, event)
            this.focusIndex = currentIndicatorInfo.index
            this.indicatorLeftMargin = currentIndicatorInfo.left
            this.tabWidth = currentIndicatorInfo.width
            this.indicatorWidth = currentIndicatorInfo.width
          })
        }
      }.scrollBar(BarState.Off)
    }.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 getCurrentIndicatorInfo(index: number, event: TabsAnimationEvent): Record<string, number> {
    let nextIndex = index
    if (index > 0 && event.currentOffset > 0) {
      nextIndex--
    } else if (index < 4 && event.currentOffset < 0) {
      nextIndex++
    }
    let indexInfo = this
分享
微博
QQ
微信
回复
2天前
相关问题
HarmonyOS 如何实现交互实现-
460浏览 • 1回复 待解决
如何实现分组列表的/底效果
2261浏览 • 1回复 待解决
HarmonyOS 如何实现折叠顶效果?
160浏览 • 1回复 待解决
页面和列表嵌套滚动,实现列表
1286浏览 • 1回复 待解决
HarmonyOS 如何监听折叠屏展开折叠
68浏览 • 1回复 待解决
HarmonyOS 流式布局折叠效果
143浏览 • 1回复 待解决
HarmonyOS 折叠屏适配资料
511浏览 • 1回复 待解决
如何实现通用的顶效果
671浏览 • 1回复 待解决
如何区分折叠屏与非折叠屏手机?
349浏览 • 0回复 待解决
HarmonyOS 折叠屏webview宽度问题
444浏览 • 1回复 待解决
Scroll容器中子组件顶效果
427浏览 • 1回复 待解决