HarmonyOS 如何在滑动容器内,实现自定义组件吸顶呢,在文档中如果子组件是容器类型的,可以用nestedScroll属性来吸顶,自己写的自定义组件如何吸顶呢

HarmonyOS
2天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
put_get

目前自定义组件吸顶效果API暂时还没有,但可以通过偏移量来实现相同效果下面的demo

enum ScrollPosition {
  start,
  center,
  end
}

class ItemClass {
  content: string = '';
  color: Color = Color.White;
}

@Entry
@Component
struct NestedScrollDemo {
  @State listPosition: number = ScrollPosition.start; // 0代表滚动到List顶部,1代表中间值,2代表滚动到List底部。
  @State scrollPosition: number = ScrollPosition.start; // 0代表滚动到页面顶部,1代表中间值,2代表滚动到页面底部。
  @State showTitle: boolean = false;
  @State currentYOffset: number = 0;
  private arr: ItemClass[] = [];
  private colorArr: Color[] = [Color.White, Color.Blue, Color.Brown, Color.Green, Color.Gray];
  private scrollerForScroll: Scroller = new Scroller();
  private scrollerForList: Scroller = new Scroller();
  private scrollerForTitle: Scroller = new Scroller();
  @State currentIndex: number = 0;

  aboutToAppear() {
    for (let i = 0; i < 6; i++) {
      let data: ItemClass = {
        content: i.toString(),
        color: this.colorArr[i % 5]
      }
      this.arr.push(data);
    }
  }

  @Builder
  myBuilder() {
    Row() {
      List({ space: 2, initialIndex: 0, scroller: this.scrollerForTitle }) {
        ForEach(this.arr, (item: ItemClass, index) => {
          ListItem() {
            Column() {
              Text(item.content);
              Divider()
                .color('#000000')
                .strokeWidth(5)
                .visibility(index == this.currentIndex ? Visibility.Visible : Visibility.Hidden)
            }
            .width('25%')
            .height(50)
            .onClick(() => {
              this.scrollerForList.scrollToIndex(index)
              this.scrollerForScroll.scrollEdge(Edge.Bottom)
            })
          }
        })
      }
      .listDirection(Axis.Horizontal)
      .scrollBar(BarState.Off)
    }
    .backgroundColor('#ffe2d0d0')
    .alignItems(VerticalAlign.Center)



    build() {
      Stack({ alignContent: Alignment.Top }) {
        Scroll(this.scrollerForScroll) {
          Column() {
            Image($r('app.media.app_icon'))
              .width("100%")
              .height("40%")
            this.myBuilder();

            List({ space: 10, scroller: this.scrollerForList }) {
              ForEach(this.arr, (item: ItemClass, index) => {
                ListItem() {
                  Column() {
                    Text(item.content)
                    //添加其他内容
                  }
                  .width('100%')
                  .height(500)
                  .backgroundColor(item.color)
                }.width("100%").height(500)
                .onVisibleAreaChange([0.8], (isVisible) => {
                  if (isVisible) {
                    this.currentIndex = index;
                    this.scrollerForTitle.scrollToIndex(this.currentIndex);
                  }
                })
              }, (item: ItemClass) => item.content)
            }
            .padding({ left: 10, right: 10 })
            .width("100%")
            .edgeEffect(EdgeEffect.None)
            .scrollBar(BarState.Off)
            .onReachStart(() => {
              this.listPosition = ScrollPosition.start
            })
            .onReachEnd(() => {
              this.listPosition = ScrollPosition.end
            })
            .onScrollFrameBegin((offset: number, state: ScrollState) => {
              // 滑动到列表中间时
              if (!((this.listPosition == ScrollPosition.start && offset < 0)
                || (this.listPosition == ScrollPosition.end && offset > 0))) {
                this.listPosition = ScrollPosition.center
              }

              // 如果页面已滚动到底部,列表不在顶部或列表有正向偏移量
              if (this.scrollPosition == ScrollPosition.end
                && (this.listPosition != ScrollPosition.start || offset > 0)) {
                return { offsetRemain: offset };
              } else {
                this.scrollerForScroll.scrollBy(0, offset)
                return { offsetRemain: 0 };
              }
            })
            .width("100%")
            .height("calc(100% - 50vp)")



            .backgroundColor('#F1F3F5')
          }
        }
        .scrollBar(BarState.Off)
        .width("100%")
        .height("100%")
        .onScroll((xOffset: number, yOffset: number) => {
          this.currentYOffset = this.scrollerForScroll.currentOffset().yOffset;

          // 非(页面在顶部或页面在底部),则页面在中间
          if (!((this.scrollPosition == ScrollPosition.start && yOffset < 0)
            || (this.scrollPosition == ScrollPosition.end && yOffset > 0))) {
            this.scrollPosition = ScrollPosition.center
          }
        })
        .onScrollEdge((side: Edge) => {
          if (side == Edge.Top) {
            // 页面在顶部
            this.scrollPosition = ScrollPosition.start
          } else if (side == Edge.Bottom) {
            // 页面在底部
            this.scrollPosition = ScrollPosition.end
          }
        })
        .onScrollFrameBegin(offset => {
          if (this.scrollPosition == ScrollPosition.end) {
            return { offsetRemain: 0 };
          } else {
            return { offsetRemain: offset };
          }
        })
      }
      .width('100%')
      .height('100%')
      .backgroundColor(0xDCDCDC)
    }
  }
分享
微博
QQ
微信
回复
2天前
相关问题
如何实现分组列表/底效果
2261浏览 • 1回复 待解决
HarmonyOS 折叠
16浏览 • 1回复 待解决
HarmonyOS 如何实现交互实现-
460浏览 • 1回复 待解决
页面和列表嵌套滚动,实现列表
1285浏览 • 1回复 待解决
ArkTs如何自定义容器组件
3110浏览 • 1回复 待解决
Scroll容器中子组件顶效果
427浏览 • 1回复 待解决
如何实现Tabs组件tarbar顶效果
1152浏览 • 1回复 待解决
自定义组件如何增加自己对外方法
1852浏览 • 1回复 待解决