HarmonyOS 仿AppBarLayout吸附使用Scroll滚动到顶时出现抖动问题

通过onScroll移动scroll上层的组件,实现吸附效果,在滚动到顶部的场景下出现抖动问题,使用onWillScroll,onDidScroll问题更明显

HarmonyOS
2024-12-18 15:55:39
795浏览
收藏 0
回答 1
回答 1
按赞同
/
按时间
aquaa

出现抖动是因为回到顶层使用了动画,然后Text没有动画效果,才会出现这样,这个目前吸顶的效果不建议在scroll的时候margin,可以参考下这个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)
  }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
分享
微博
QQ
微信
回复
2024-12-18 16:54:20


相关问题
HarmonyOS scroll滚动问题
687浏览 • 1回复 待解决
HarmonyOS Scroll组件滚动问题
1399浏览 • 1回复 待解决
Web组件怎么知道滚动到顶部了
1340浏览 • 1回复 待解决
仿射变换后列表滑动问题
966浏览 • 1回复 待解决
HarmonyOS scroll动问题
1107浏览 • 1回复 待解决
Scroll中点击某一个层图片移动到顶
1385浏览 • 1回复 待解决
HarmonyOS Scroll嵌套List的滑动问题
740浏览 • 1回复 待解决
HarmonyOS Tabs组件的Tab栏滚动问题
1496浏览 • 1回复 待解决
HarmonyOS 图片放大后的滚动动问题
653浏览 • 1回复 待解决
鸿蒙如何仿ios风?问题出现在哪里?
281浏览 • 1回复 待解决
Grid嵌套滚动问题有知道的吗?
3582浏览 • 1回复 待解决
HarmonyOS Scroll使用问题
645浏览 • 1回复 待解决
Scroll初始自动滚动一段距离
1681浏览 • 1回复 待解决