DEV Community

HarmonyOS
HarmonyOS

Posted on

How to Achieve Elastic Distance at the Edge of Swiper Control

Read the original article:How to Achieve Elastic Distance at the Edge of Swiper Control

Problem Description

When using Swiper to display content, elastic stretching can be triggered by swiping up or down when the list is at the first or last item. However, the distance of the elastic stretching is too long. Is it possible to set the height of the elastic stretching in Swiper?

Background Knowledge

For Swiper-related content, you can refer to the official documentation Swiper API. The official documentation does not provide a ready-made interface to set the edge bounce distance, so some modifications are needed based on the existing interfaces.

Troubleshooting Process

  1. Reproduce & baseline
    • Put a Swiper with 3–5 items in a simple page.
    • Swipe past the first/last item vertically and note the overscroll distance (~2/5 of screen).
    • Confirm the default edge effect is enabled (the “stretch”/bounce is visible).
  2. Check for a public API
    • Review Swiper props & methods (EffectMode, index, onChange, etc.).
    • Result: No public prop controls the edge-bounce distance (as stated in docs).
  3. Disable system effect
    • Set .EffectMode(EdgeEffect.None) on Swiper.
    • Expected: built-in stretch is gone; you’ll now need to implement your own.
  4. Prototype a custom overscroll
    • Attach a PanGesture({ direction: PanDirection.Vertical }) via .parallelGesture(...).
    • Track offsetY only when:
      • index == 0 and offsetY > 0 (pulling down at first item), or
      • index == lastIndex and offsetY < 0 (pulling up at last item).
    • Apply translate({ y: traY }) to the visible slide.

Analysis Conclusion

  • Root cause: Swiper does not expose any public API to configure the built-in edge-bounce distance. The default system effect can feel too elastic (≈ 2/5 screen).
  • Resolution approach: Disable the system edge effect with .EffectMode(EdgeEffect.None), then implement a custom overscroll using a vertical PanGesture that:

    • Activates only at the first/last slide,
    • Clamps the translation to a small, predictable limit (e.g., 48–64vp),
    • Applies nonlinear resistance for a natural “rubber-band” feel, and
    • Animates back quickly on release.

Solution

You can disable the built-in edge bounce effect of Swiper and use a custom edge bounce action. Refer to the following code:

Swiper(this.swiperController) {
  Text() // Carousel content
    .translate({
      x: this.traX,
      y: this.traY // Offset set to the captured offset
    })
}
.EffectMode(EdgeEffect.None) // Disable built-in edge effects
.parallelGesture(
  PanGesture({ direction: PanDirection.Vertical })
    .onActionUpdate((event) => {
      // Control the sliding distance here, the first one slides down
      if (this.index == 0 && event.offsetY < 50) {
        this.traY = event.offsetY
      }
      // Control the sliding distance here, the last one slides up
      if (this.index == this.data.totalCount() - 1 && event.offsetY > -50) {
        this.traY = event.offsetY
      }
    })
    .onActionEnd((event) => {
      console.info(JSON.stringify(event))
      animateTo({
        duration: 100, // Here you can control the rebound speed
        curve: Curve.EaseOut,
        iterations: 1,
        playMode: PlayMode.Normal,
        onFinish: () => {
          console.info('play end')
        }
      }, () => {
        this.traY = 0
      })
    })
)
Enter fullscreen mode Exit fullscreen mode

Verification Result

In cases where the system interface behavior does not align with expectations, the default functionality of the system interface can be disabled, and the relevant interfaces can be rewritten to achieve the desired outcome.

Written by Taha Enes Kon

Top comments (0)