如何实现scroll容器嵌套子组件,实现子组件吸顶效果

使用垂直滑动的scroll容器中,自上而下依次包含Text1、Text2、List三个子组件,上滑scroll容器,滑至Text2子组件处,Text2吸顶,List子组件中内容可继续滑动。不清楚此场景下Text2吸顶效果可如何实现?

HarmonyOS
2024-04-29 23:41:41
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
fanyu0803

原生的吸顶效果API暂时还没有,但可以通过偏移量来实现相同效果,代码如下:

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
微信
回复
2024-04-30 22:04:29
相关问题
自定义组件嵌套子组件
7429浏览 • 3回复 待解决
如何实现分组列表的顶/效果
358浏览 • 1回复 待解决
嵌套组件Scroll不生效
191浏览 • 1回复 待解决
Scroll组件的展示位置如何调整
414浏览 • 1回复 待解决
Text实现scroll效果怎么弄?
3481浏览 • 1回复 待解决
List组件如何实现多列效果
282浏览 • 1回复 待解决
如何设置组件透明效果
131浏览 • 1回复 待解决
组件如何设置模糊效果
323浏览 • 1回复 待解决
如何设置父组件组件宽度变化
313浏览 • 1回复 待解决
组件如何处理组件内点击事件
593浏览 • 1回复 待解决
ArkTs如何自定义容器组件
1117浏览 • 1回复 待解决
如何隐藏容器组件的溢出内容
562浏览 • 1回复 待解决
容器组件onVisibleAreaChange不生效
150浏览 • 1回复 待解决
Image组件如何实现双指手势放大
252浏览 • 1回复 待解决
组件如何实现渐变色?
517浏览 • 1回复 待解决