# 如何实现Swiper控制最边缘时的弹性距离

#### 问题现象

使用Swiper展示内容时，在列表的第一个和最后一个展示时，可以通过上划或者下划触发弹性伸缩。但是，弹性伸缩的距离过长。是否可以设置Swiper中弹性伸缩的高度，如下图拉到最下面伸缩的距离大概有2/5：

把第一个内容拉到最下面伸缩距离固定：

#### 背景知识

Swiper相关内容可以参考官方文档Swiper API。官方文档中没有现成的接口设置边缘回弹距离，需要在原有接口的基础上进行一些更改。

#### 解决方案

可以通过禁用Swiper内置的边缘回弹效果，使用自定义边缘的回弹动作。参考如下代码：

```
// xxx.ets
class MyDataSource implements IDataSource {
  private list: number[] = [];

  constructor(list: number[]) {
    this.list = list;
  }

  totalCount(): number {
    return this.list.length;
  }

  getData(index: number): number {
    return this.list[index];
  }

  registerDataChangeListener(): void {
  }

  unregisterDataChangeListener() {
  }
}

@Entry
@Component
export struct SwiperExample {
  private swiperController: SwiperController = new SwiperController();
  private data: MyDataSource = new MyDataSource([]);
  @State traY: number = 0;
  @State index: number = 0;

  aboutToAppear(): void {
    let list: number[] = [];
    for (let i = 1; i <= 10; i++) {
      list.push(i);
    }
    this.data = new MyDataSource(list);
  }

  build() {
    Column({ space: 5 }) {
      Swiper(this.swiperController) {
        LazyForEach(this.data, (item: string) => {
          Text(item.toString())
            .width('90%')
            .height(400)
            .backgroundColor(0xAFEEEE)
            .textAlign(TextAlign.Center)
            .fontSize(30)
            .translate({
              y: this.traY   // 偏移设置为捕获到的偏移量
            });
        }, (item: string) => item);
      }
      .backgroundColor(Color.Orange)
      .onChange((index: number) => {
        this.index = index;
      })
      .loop(false)
      .vertical(true)
      .effectMode(EdgeEffect.None) // 禁用内置边缘效果
      .parallelGesture(
        PanGesture({ direction: PanDirection.Vertical })
          .onActionUpdate((event) => {
            // 这里控制滑动距离，第一个往下滑
            if (this.index == 0 && event.offsetY < 160) {
              this.traY = event.offsetY;
            }
            // 这里控制滑动距离，最后一个往上滑
            if (this.index == this.data.totalCount() - 1 && event.offsetY > -160) {
              this.traY = event.offsetY;
            }
          })
          .onActionEnd(() => {
            animateToImmediately({
              duration: 100, // 这里可以控制回弹速度
              curve: Curve.EaseOut,
              iterations: 1,
              playMode: PlayMode.Normal,
            }, () => {
              this.traY = 0;
            });
          })
      );
    }.width('100%')
    .margin({ top: 50 });
  }
}
```

#### 总结

对于系统接口行为与预期不符的情况，可以禁用系统接口的默认功能，并重写相关接口以实现预期效果。