文档管理中心
FAQ应用框架开发UI框架UI界面List如何实现滑动翻页效果

List如何实现滑动翻页效果

问题现象

List有无enablePaging类似的方法?Scroll嵌套List后的enablePaging会失效吗?

背景知识

  • List列表包含一系列相同宽度的列表项。
  • Scroll可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。
    • enablePaging设置是否支持滑动翻页。如果同时设置了滑动翻页enablePaging和限位滚动scrollSnap,则scrollSnap优先生效。List没有类似方法。
  • Scroller可滚动容器组件的控制器,可以将此组件绑定至容器组件,如Scroll、List等。
    • scrollTo滑动到指定位置,可设置滑动的动画效果。
    • currentOffset获取当前的滚动偏移量。
  • onAreaChange组件区域变化时触发该回调,可获取组件的尺寸信息。
  • onTouch手指触摸动作触发该回调。包含触摸类型,触摸点坐标等信息。

解决方案

  • 方案一:在外层使用Scroll包裹List组件,用Scroll的enablePaging方法替代。内层的List不能设置滚动方向上的组件长度,否则enablePaging方法会失效。示例代码如下:此时List本身是不可滚动的,外层Scroll可以滚动。
    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct ScrollSolution {
    4. private arr: number[] = new Array(30).fill(0);
    5. private scroller: Scroller = new Scroller();
    6. @State centerIndex: number = 0;
    7. build() {
    8. Column() {
    9. Scroll() {
    10. List({ space: 20, scroller: this.scroller }) {
    11. ForEach(this.arr, (item: number, index: number) => {
    12. ListItem() {
    13. Text(`Item ${index}`)
    14. .width('100%')
    15. .height(100)
    16. .fontSize(16)
    17. .textAlign(TextAlign.Center)
    18. .borderRadius(10)
    19. .backgroundColor(this.centerIndex === index ? '#0A59F7' : '#F1F3F5');
    20. }
    21. .onClick(() => {
    22. this.centerIndex = index;
    23. this.scroller.scrollToIndex(this.centerIndex, true, ScrollAlign.CENTER);
    24. });
    25. }, (item: number) => item.toString());
    26. }
    27. // 上下滚动,不能设置List的高度,否则Scroll的enablePaging会失效
    28. .width('100%');
    29. }
    30. .enablePaging(true) // 滑动翻页
    31. .friction(0.8) // 设置摩擦系数
    32. .width('100%')
    33. .height('100%');
    34. }.margin('20vp');
    35. }
    36. }

    效果如下:

  • 方案二:自定义实现List翻页效果。通过onAreaChange获取List的高度,在onTouch回调中实现滑动翻页逻辑,手指按下时,获取当前List的滚动偏移量,手指抬起时,根据手指滑动方向决定向前或向后滚动一个List高度的距离。示例代码如下:翻页判定条件为手指滑动List的距离超过List高度的三分之一。
    收起
    自动换行
    深色代码主题
    复制
    1. @Entry
    2. @Component
    3. struct ListSolution {
    4. private arr: number[] = new Array(30).fill(0);
    5. private scroller: Scroller = new Scroller();
    6. @State centerIndex: number = 0;
    7. @State listHeight: number = 0;
    8. @State listWidth: number = 0;
    9. @State listOffset: number = 0; // List偏移量
    10. build() {
    11. Column() {
    12. List({ space: 20, scroller: this.scroller }) {
    13. ForEach(this.arr, (item: number, index: number) => {
    14. ListItem() {
    15. Text(`Item ${item + index}`)
    16. .width('100%')
    17. .height(100)
    18. .fontSize(16)
    19. .textAlign(TextAlign.Center)
    20. .borderRadius(10)
    21. .backgroundColor(this.centerIndex === index ? '#0A59F7' : '#F1F3F5');
    22. }
    23. .onClick(() => {
    24. this.centerIndex = index;
    25. // 点击某一项,此项移动至屏幕中间
    26. this.scroller.scrollToIndex(this.centerIndex, true, ScrollAlign.CENTER);
    27. });
    28. }, (item: number) => item.toString());
    29. }
    30. .edgeEffect(EdgeEffect.None)
    31. .onAreaChange((oldValue: Area, newValue: Area) => {
    32. console.info(`${JSON.stringify(oldValue)} ${JSON.stringify(newValue)}`);
    33. this.listHeight = newValue.height as number;
    34. this.listWidth = newValue.width as number;
    35. })
    36. .onTouch((event: TouchEvent) => {
    37. if (event.type === TouchType.Down) {
    38. // 记录手指按下时的偏移量
    39. this.listOffset = this.scroller.currentOffset().yOffset;
    40. console.info(`this.currentOffset ${this.listOffset}`);
    41. }
    42. if (event.type === TouchType.Up || event.type === TouchType.Cancel) {
    43. // 滑动距离超过页面三分之一则整页滚动
    44. let curOffset: number = this.scroller.currentOffset().yOffset - this.listOffset;
    45. let targetOffset = this.listOffset;
    46. if (Math.abs(curOffset) < this.listHeight / 3) {
    47. targetOffset = this.listOffset;
    48. } else if (curOffset > 0) {
    49. targetOffset = this.listOffset + this.listHeight;
    50. } else if (curOffset < 0) {
    51. targetOffset = this.listOffset - this.listHeight;
    52. }
    53. console.info(`targetOffset ${targetOffset} listOffset ${curOffset} `);
    54. this.scroller.scrollTo({
    55. xOffset: 0,
    56. yOffset: targetOffset,
    57. animation: true
    58. });
    59. }
    60. })
    61. .height('100%')
    62. .width('100%');
    63. }.margin('20vp');
    64. }
    65. }

    效果如下:实现整页滑动以及点击Item自动移动至屏幕中间:

在 FAQ 中进行搜索
请输入您想要搜索的关键词