Contents

fxm90/gradientloadingbar

A customizable animated gradient loading bar, with full support for **SwiftUI** and **UIKit**.\

Requirements

  • Swift 6.2
  • Xcode 26
  • iOS 26.0+

Compatibility Notes

  • iOS < 26.0 / CocoaPods / Carthage support

Use version 3.x.x

  • iOS < 13.0 support

Use version 2.x.x

Installation

Swift Package Manager

Gradient Loading Bar is distributed via Swift Package Manager (SPM). Add it to your Xcode project as a package dependency or adapt your Package.swift file.

Option 1: Xcode
  1. Open your project in Xcode
  2. Go to File → Add Packages…
  3. Enter the package URL: https://github.com/fxm90/GradientLoadingBar
  4. Choose the version rule (e.g. Up to Next Major starting at 4.0.0)
  5. Add the package to your target
Option 2: Package.swift

If you manage dependencies manually, add this repository to the dependencies section of your Package.swift:

dependencies: [
  .package(
  url: "https://github.com/fxm90/GradientLoadingBar",
  from: "4.0.0"
  )
]

Then reference the product in your target configuration:

.product(
  name: "GradientLoadingBar",
  package: "GradientLoadingBar"
)

Once the package is added, import the framework where needed:

import GradientLoadingBar

Overview

This framework provides four types:

A controller class, managing the visibility of the GradientActivityIndicatorView attached to the current key window.

A subclass of GradientLoadingBar, wrapping the GradientActivityIndicatorView around the iPhone notch.

A UIView containing the gradient with the animation.

A SwiftUI View containing the gradient with the animation.

GradientLoadingBar

GradientLoadingBar is a controller-style object that manages a gradient loading bar attached to the app’s key window.

Usage

For most use cases, prefer the shared instance provided by GradientLoadingBar.shared.

final class UserProfileViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    GradientLoadingBar.shared.fadeIn()

    userProfileService.fetchUserProfile { _ in
      // ...
      // Be sure to call this from the main actor!
      GradientLoadingBar.shared.fadeOut()
    }
  }
}

This shared instance can be overridden to customize the loading bar globally.

Configuration

let gradientLoadingBar = GradientLoadingBar(
  height: 5.0,
  isRelativeToSafeArea: false,
)

gradientLoadingBar.gradientColors = [.systemIndigo, .systemPurple, .systemPink]
gradientLoadingBar.progressAnimationDuration = 4.5
Parameters
  • height: CGFloat\

Sets the bar height (default: 3.0)

  • isRelativeToSafeArea: Bool\

Determines whether the bar is positioned relative to the safe area (default: true)

| Relative To Safe Area | Ignoring Safe Area | | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | | [![Relative to Safe Area][relative-to-safe-area-thumbnail]][relative-to-safe-area] | [![Ignoring Safe Area][ignoring-safe-area-thumbnail]][ignoring-safe-area] |

The gradient animation is easier to see in a video of the example application:

<details> <summary>🎬 Relative To Safe Area</summary>

https://github.com/user-attachments/assets/c8a3a117-c164-49f5-9511-aa29b92b5344 </details>

<details> <summary>🎬 Ignoring Safe Area</summary>

https://github.com/user-attachments/assets/4abad13d-e019-43b3-b3b3-c874ac8f9224 </details>

Note: For a third option — wrapping around the iPhone notch — see NotchGradientLoadingBar.

Properties
  • gradientColors: [UIColor]\

Defines the gradient colors.

  • progressAnimationDuration: TimeInterval\

Controls how fast the gradient animates from left to right.

Methods
  • fadeIn(duration: TimeInterval = 0.33, completion: ((Bool) -> Void)? = nil)\

Fades the loading bar in.

  • fadeOut(duration: TimeInterval = 0.66, completion: ((Bool) -> Void)? = nil)\

Fades the loading bar out.

NotchGradientLoadingBar

NotchGradientLoadingBar is a subclass of GradientLoadingBar that wraps the bar around the iPhone notch.\ On devices without a notch, it behaves identically to GradientLoadingBar.

| iPhone 12 Pro | iPhone 13 Pro Max | | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | | [![iPhone 12 Pro][notch-iphone-12-pro-thumbnail]][notch-iphone-12-pro] | [![iPhone 13 Pro Max][notch-iphone-13-pro-max-thumbnail]][notch-iphone-13-pro-max] |

The gradient animation is easier to see in a video of the example application:

<details> <summary>🎬 iPhone 12 Pro</summary>

https://github.com/user-attachments/assets/998fe36c-40c5-4c70-9ce8-e7a7f3f126d8 </details>

<details> <summary>🎬 iPhone 13 Pro Max</summary>

https://github.com/user-attachments/assets/2ff6d717-07f1-4d70-887e-2727d55f2515 </details>

GradientActivityIndicatorView

If you prefer direct view composition, GradientActivityIndicatorView is a UIView subclass that can be added to other views — such as UINavigationBar, UIButton or a custom container.

Usage

Store an instance as a property, set up constraints and control the visibility using fadeIn() and fadeOut().

final class UserProfileViewController: UIViewController {

  private let gradientActivityIndicatorView = GradientActivityIndicatorView()

  // ...

  override func viewDidLoad() {
    super.viewDidLoad()

    gradientActivityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(gradientActivityIndicatorView)

    NSLayoutConstraint.activate([
      gradientActivityIndicatorView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
      gradientActivityIndicatorView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
      gradientActivityIndicatorView.topAnchor.constraint(equalTo: view.topAnchor),
      gradientActivityIndicatorView.heightAnchor.constraint(equalToConstant: 3),
    ])

    gradientActivityIndicatorView.fadeIn()

    userProfileService.fetchUserProfile { [weak self] _ in
      // ...
      // Be sure to call this from the main actor!
      self?.gradientActivityIndicatorView.fadeOut()
    }
  }
}

Configuration

let gradientActivityIndicatorView = GradientActivityIndicatorView()
gradientActivityIndicatorView.gradientColors = [.systemIndigo, .systemPurple, .systemPink]
gradientActivityIndicatorView.progressAnimationDuration = 4.5
Properties
  • isHidden: Bool\

Toggles the view visibility and starts / stops the progress animation accordingly.

  • gradientColors: [UIColor]\

Defines the gradient colors.

  • progressAnimationDuration: TimeInterval\

Controls how fast the gradient animates from left to right.

Methods
  • fadeIn(duration: TimeInterval = 0.33, completion: ((Bool) -> Void)? = nil)\

Fades the view in.

  • fadeOut(duration: TimeInterval = 0.66, completion: ((Bool) -> Void)? = nil)\

Fades the view out.

  • animate(isHidden: Bool, duration: TimeInterval, completion: ((Bool) -> Void)? = nil)\

Fades the view in- or out, based on the provided hidden flag.

GradientLoadingBarView

GradientLoadingBarView is the SwiftUI equivalent of GradientActivityIndicatorView.

Usage

struct ContentView: View {

  var body: some View {
    GradientLoadingBarView()
      .frame(maxWidth: .infinity, maxHeight: 3)
      .cornerRadius(1.5)
  }
}

Configuration

GradientLoadingBarView(
  gradientColors: [.indigo, .purple, .pink],
  progressDuration: 4.5,
)
Parameters
  • gradientColors: [Color]\

Defines the gradient colors.

  • progressDuration: TimeInterval\

Sets the animation speed.

Visibility & Animation

Control the visibility using standard SwiftUI view modifiers such as:

Example with fade animation.

struct ContentView: View {

  @State
  private var isVisible = false

  var body: some View {
    VStack {
      GradientLoadingBarView()
        .frame(maxWidth: .infinity, maxHeight: 3)
        .cornerRadius(1.5)
        .opacity(isVisible ? 1 : 0)
        .animation(.easeInOut, value: isVisible)

      Button("Toggle visibility") {
        isVisible.toggle()
      }
    }
  }
}

Author

Felix Mau me(@)felix.hamburg

License

Gradient Loading Bar is released under the MIT License. See the LICENSE file for details.

[example]: Assets/screen.gif [ignoring-safe-area]: Assets/ignoring-safe-area.png [ignoring-safe-area-thumbnail]: Assets/ignoring-safe-area-thumbnail.png [ignoring-safe-area-animation]: Assets/ignoring-safe-area.mov [relative-to-safe-area]: Assets/relative-to-safe-area.png [relative-to-safe-area-thumbnail]: Assets/relative-to-safe-area-thumbnail.png [relative-to-safe-area-animation]: Assets/relative-to-safe-area.mov [notch-iphone-12-pro]: Assets/notch-iphone-12-pro.png [notch-iphone-12-pro-thumbnail]: Assets/notch-iphone-12-pro-thumbnail.png [notch-iphone-12-pro-animation]: Assets/notch-iphone-12-pro.mov [notch-iphone-13-pro-max]: Assets/notch-iphone-13-pro-max.png [notch-iphone-13-pro-max-thumbnail]: Assets/notch-iphone-13-pro-max-thumbnail.png [notch-iphone-13-pro-max-animation]: Assets/notch-iphone-13-pro-max.mov

Package Metadata

Repository: fxm90/gradientloadingbar

Default branch: main

README: README.md