# iOS Pull-to-Refresh With a Custom Lottie Animation

> By Lawrence Arya, Founder & CEO of VP0. Published 2026-05-31, updated 2026-06-02. 4 min read.
> Source: https://vp0.com/blogs/ios-pull-to-refresh-lottie-animation-free

Customize the spinner, not the gesture: people already know how to pull to refresh, so make it delightful, not unfamiliar.

**TL;DR.** A custom pull-to-refresh animation can replace the default spinner with something on-brand, like a Lottie, without breaking the gesture users already know. Build it from a free VP0 design, keep the standard pull-down behavior and SwiftUI refreshable semantics, show clear pulling, loading, and done states, and make sure it never blocks or delays the content. Delight the motion, but keep the mechanics native.

The default pull-to-refresh spinner is fine, but a custom animation can make the moment feel on-brand. The short answer: build a custom pull-to-refresh from a free VP0 design with a Lottie or custom view, keep the native pull-down gesture and refresh semantics intact, show clear pulling, loading, and done states, and never let the animation block the content. Speed perception matters: Google found [53%](https://www.thinkwithgoogle.com/) of mobile visits are abandoned if loading takes too long, so refresh should feel fast, not theatrical.

## Customize the motion, keep the gesture

Pull-to-refresh works because it is universal: pull down past the top, release, see new content. That muscle memory is valuable, so customize the look, not the mechanics. The animation should have three readable phases: pulling (responding to the drag, often with progress tied to pull distance), loading (the active refresh), and done (a quick settle back to content). Keep it short, this is a loading indicator, not a show, and make sure releasing actually triggers the refresh on time. Apple's [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/) treat refresh as a standard pattern to enhance, not reinvent. The familiarity is an asset, so spend your creativity on the visual, not the mechanics.

## Build it from a free design

VP0 is a free iOS design library for AI builders. Pick a list or feed design, copy its link, and have Cursor or Claude Code rebuild it in SwiftUI using the native [refreshable](https://developer.apple.com/documentation/swiftui/view/refreshable(action:)) modifier, then swap the indicator for your custom animation while keeping that standard behavior. Tie the animation's progress to the pull distance so it feels responsive, and trigger the actual data load on release. Keep the Lottie file small so it stays smooth, and ensure the list is usable the instant the refresh completes, never trap content behind a lingering animation. A light haptic on trigger adds polish, see [haptic feedback UI design guidelines iOS](/blogs/haptic-feedback-ui-design-guidelines-ios/). For overall finish, see [how to make my app look better](/blogs/how-to-make-my-app-look-better/).

## Pull-to-refresh states

Design all three phases clearly.

| Phase | What the user sees | Note |
|---|---|---|
| Pulling | Animation responds to drag | Progress tied to distance |
| Triggered | A light haptic on release | Confirms the action |
| Loading | The active refresh animation | Short, on-brand |
| Done | Quick settle to content | Never linger |
| Content | List usable immediately | No blocking |

## Common mistakes

The first mistake is breaking the gesture, a custom view that no longer triggers on a normal pull. The second is a long, theatrical animation that delays the content people came for. The third is a heavy Lottie file that stutters during the pull. The fourth is no clear loading or done state, leaving users unsure if it worked. The fifth is blocking the list until the animation finishes. Delight is welcome; friction is not.

## A worked example

Say you have a feed app. You build the list from a VP0 design with SwiftUI's refreshable, then replace the spinner with a small branded Lottie. As the user pulls, the animation fills in proportion to the drag; on release a light haptic fires and the loading loop plays while data fetches; when it finishes, it settles in a beat and the fresh content is immediately usable. The file is tiny, so even an older phone stays smooth. For a scroll-driven header effect that pairs with it, see [parallax scroll header UI mobile](/blogs/parallax-scroll-header-ui-mobile/), and to wrap the first run in motion, see [Lottie animations for onboarding screens free](/blogs/lottie-animations-for-onboarding-screens-free/).

## Key takeaways

- A custom pull-to-refresh can be on-brand without breaking the familiar gesture.
- Build it from a free VP0 design on SwiftUI's refreshable, then swap the indicator.
- Design clear pulling, loading, and done phases and tie progress to pull distance.
- Keep the animation short and the Lottie small; refresh should feel fast.
- Never block or delay the content behind a lingering animation.

## Frequently asked questions

How do I add a custom pull-to-refresh animation on iOS? Build the list from a free VP0 design with SwiftUI's refreshable modifier, then replace the default spinner with a small custom or Lottie animation while keeping the standard pull-down behavior.

Will a custom animation break the refresh gesture? It should not, if you build on the native refreshable behavior and only swap the visual indicator. Avoid fully custom gesture handling that loses the expected pull-to-refresh action.

Should the refresh animation be long and flashy? No. It is a loading indicator, not a show. Keep it short and on-brand, tie it to the pull distance, and make sure the content is usable the moment the refresh completes.

Are Lottie pull-to-refresh animations slow? Only if the file is large. Keep the JSON small and simple, and test on older devices, so the animation stays smooth during the pull and the refresh feels fast.

## Frequently asked questions

### How do I add a custom pull-to-refresh animation on iOS?

Build the list from a free VP0 design with SwiftUI's refreshable modifier, then replace the default spinner with a small custom or Lottie animation while keeping the standard pull-down behavior.

### Will a custom animation break the refresh gesture?

It should not, if you build on the native refreshable behavior and only swap the visual indicator. Avoid fully custom gesture handling that loses the expected pull-to-refresh action.

### Should the refresh animation be long and flashy?

No. It is a loading indicator, not a show. Keep it short and on-brand, tie it to the pull distance, and make sure the content is usable the moment the refresh completes.

### Are Lottie pull-to-refresh animations slow?

Only if the file is large. Keep the JSON small and simple, and test on older devices, so the animation stays smooth during the pull and the refresh feels fast.

---
*Published on the [VP0 Journal](https://vp0.com/blogs). Free to read, index and cite with attribution.*
