Creating custom animations for iOS apps is a valuable investment that helps you create a more engaging, memorable, and user-friendly experience for your app users. Even the smallest interactions like page refreshing can be visually appealing and contribute to the overall impression.
Pull-to-refresh functionality has become a staple feature, offering people a seamless way to update page content. While SwiftUI offers a built-in RefreshControl, integrating Lottie iOS animations — a popular choice for adding dynamic visual elements — alongside native animations can be a challenge.
In standard SwiftUI components, the animation is a simple spinner. If you want a custom animation, you need a non-standard iOS control. However, it’s hard to find pull-to-refresh solutions for SwiftUI on the Internet or GitHub that you can just take and install. Moreover, most of them use standard controls without customization options or Lottie support.
To save you from writing chunks of code, the Shakuro developers have built a component for implementing and customizing iOS pull-to-refresh in your future app. Dive in to learn how you can integrate it to simplify your workflow and win your users’ hearts with a simple swipe.
Why pick our iOS pull-to-refresh package?
- As we said, you can create visually appealing custom animations with progress bars for your iOS app.
- During iOS app development, you work not only with native animations but also with Lotties – JSON files made by UI/UX designers. Compared with standard solutions, our pull-to-refresh components support native and Lottie animations with progress bars.
- What’s more, it doesn’t have any dirty hacks. Beginner developers quite often meddle with the UIKit to get the desired functionality in SwiftUI. They write their own code that can do more harm than good. When we created the components, we used only native code. So no introspecting views hierarchy or UIKit wrappers.
- The package is easy to install. You can integrate it using Swift Package Manager, CocoaPods, or even manually.
How our Pull-to-Refresh works
When you tap and pull the page down, the animation kicks off and the data starts to refresh. Once the page data is updated, the animation stops and the user sees the new info. The main goal of this control is to trigger the data refreshing event and show the animation while data is being updated in the background.
Our UI package contains two controls: PullToRefreshScrollView and PullToRefreshListView. With these controls, you add the animation into SwiftUI ScrollView and List containers.
Let’s dwell on each control and its implementation.
PullToRefreshScrollView
It is a custom control that allows you to place and update any content on scroll view with a pull-to-refresh action.
Here’s an example of using PullToRefreshScrollView:
PullToRefreshScrollView(
options: PullToRefreshScrollViewOptions(pullToRefreshAnimationHeight: 100,
animationDuration: 0.3,
animatePullingViewPresentation: true,
animateRefreshingViewPresentation: true),
isRefreshing: $isRefreshing,
onRefresh: {
debugPrint("Refreshing")
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(5), execute: {
isRefreshing = false
})
},
animationViewBuilder: { (state) in
switch state {
case .idle:
Color.clear
case .pulling(let progress):
ProgressView(value: progress, total: 1)
.progressViewStyle(.linear)
case .refreshing:
ProgressView()
.progressViewStyle(.circular)
}
},
contentViewBuilder: { _ in
Color(.lightGray)
.frame(height: 1000)
})
PullToRefreshListView
With this custom control, you can add and refresh content to the list view with a custom animation.
Look at this example showing how you can use PullToRefreshListView:
PullToRefreshListView(
options: PullToRefreshListViewOptions(pullToRefreshAnimationHeight: 100,
animationDuration: 0.3,
animatePullingViewPresentation: true,
animateRefreshingViewPresentation: true),
isRefreshing: $isRefreshing,
onRefresh: {
debugPrint("Refreshing")
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(5), execute: {
isRefreshing = false
})
},
animationViewBuilder: { (state) in
switch state {
case .idle:
Color.clear
case .pulling(let progress):
ProgressView(value: progress, total: 1)
.progressViewStyle(.linear)
case .refreshing:
ProgressView()
.progressViewStyle(.circular)
}
},
contentViewBuilder: { _ in
ForEach(0..<5, content: { (item) in
Text("Item \(item)")
})
})
When triggered, the UI component uses the onRefresh callback to start the refreshing action. To start or stop the refreshing state outside the animation, it relies on the isRefreshing binding value.
For example, when the refresh action is finished, you can stop refreshing the animation by setting the isRefreshing parameter to false.
To isolate the animation from the content view, the SwiftUI components apply .geometryGroup() for iOS 17 or .transformEffect(.identity) for iOS 15 and 16.
The pull-to-refresh animation has 3 states:
– Idle: waiting for the trigger;
– Pulling with current progress: the user touches the screen and drags it down to refresh the content. Progress is the value from 0 (idle) to 1 (refreshing). Pulling animation can be interactive and follow current progress.
– Refreshing: when progress turns to 1, the refresh is triggered and it actualizes the info on the page.
Leverage the iOS SwiftUI Pull-to-Refresh components to your advantage
With the power of SwiftUI‘s native animation capabilities and Lottie dynamic animations, you create refresh controls that function flawlessly and impress users with captivating visuals. Thanks to the plain SwiftUI code used in the package, you integrate and create custom animations hassle-free.
The Shakuro team offers more useful solutions for app development: pre-made UI components, Swift libraries, frameworks, etc. So if you are looking for a way to cut corners, check out the Shakuro GitHub repository. You will find examples of various apps’ parts, processes, and interfaces.
Do you want to develop an app with custom animations? Contact us to build a functional and visually appealing product.
Written by Mary Moore and Sergey Popov