UIActivityIndicator
iOS development
user interface
customization
iOS programming

Can I change the size of UIActivityIndicator?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

UIActivityIndicatorView does not let you pick an arbitrary diameter the way you would size a normal UIView. Apple exposes a small set of built-in styles, and anything outside those sizes is a visual workaround rather than a true layout-level resize.

What Apple actually supports

The first thing to know is that changing the frame usually does not change how the spinner is drawn. The control decides its own intrinsic size based on style.

On modern iOS versions, the main supported options are medium and large:

swift
let spinner = UIActivityIndicatorView(style: .large)
spinner.color = .systemBlue
spinner.startAnimating()

If the built-in sizes are acceptable, use them. They are the most predictable option for Auto Layout, accessibility, and future iOS updates.

You can still position the spinner with constraints:

swift
1spinner.translatesAutoresizingMaskIntoConstraints = false
2view.addSubview(spinner)
3
4NSLayoutConstraint.activate([
5    spinner.centerXAnchor.constraint(equalTo: view.centerXAnchor),
6    spinner.centerYAnchor.constraint(equalTo: view.centerYAnchor)
7])

That code moves the indicator, but it does not change the actual rendered size.

Use a transform when you need a visual resize

If you need the spinner to look larger or smaller than Apple provides, the usual workaround is scaling it with CGAffineTransform.

swift
let spinner = UIActivityIndicatorView(style: .medium)
spinner.transform = CGAffineTransform(scaleX: 1.6, y: 1.6)
spinner.startAnimating()

This works because the view is being visually scaled after it is laid out. It is useful when a design system calls for a slightly bigger loading indicator, but there are tradeoffs:

  • the control is not truly redrawn at a new native size
  • surrounding layout may still behave as if the original intrinsic size is in use
  • very large scaling can look soft or awkward

For moderate adjustments, it is usually fine. For dramatic resizing, it starts to feel like a hack.

Layout still matters after scaling

A common mistake is scaling the spinner and forgetting that the surrounding constraints may no longer leave enough space. If you scale a medium spinner to double size, its visual footprint is larger than the layout system expects.

One clean pattern is to place the spinner inside a container view and constrain the container instead of relying on the spinner's intrinsic size alone:

swift
1let container = UIView()
2container.translatesAutoresizingMaskIntoConstraints = false
3spinner.translatesAutoresizingMaskIntoConstraints = false
4
5container.addSubview(spinner)
6view.addSubview(container)
7
8spinner.centerXAnchor.constraint(equalTo: container.centerXAnchor).isActive = true
9spinner.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
10
11NSLayoutConstraint.activate([
12    container.widthAnchor.constraint(equalToConstant: 60),
13    container.heightAnchor.constraint(equalToConstant: 60),
14    container.centerXAnchor.constraint(equalTo: view.centerXAnchor),
15    container.centerYAnchor.constraint(equalTo: view.centerYAnchor)
16])

This makes the visual result more predictable when the spinner is scaled.

Use a custom loading view for exact control

If your design requires a specific diameter, stroke width, brand color animation, or a custom motion pattern, UIActivityIndicatorView is probably the wrong component. In that case, build a small custom loading view with CAShapeLayer or use an animated image or symbol.

Here is a minimal custom spinner using a shape layer:

swift
1let circle = CAShapeLayer()
2circle.path = UIBezierPath(
3    arcCenter: CGPoint(x: 20, y: 20),
4    radius: 16,
5    startAngle: 0,
6    endAngle: .pi * 1.5,
7    clockwise: true
8).cgPath
9circle.strokeColor = UIColor.systemBlue.cgColor
10circle.fillColor = UIColor.clear.cgColor
11circle.lineWidth = 3
12
13let rotation = CABasicAnimation(keyPath: "transform.rotation")
14rotation.toValue = Double.pi * 2
15rotation.duration = 0.8
16rotation.repeatCount = .infinity
17
18circle.add(rotation, forKey: "spin")

That approach takes more code, but it gives real control over size and appearance.

Pick the simplest option that matches the requirement

If the question is "can I make it a little bigger," use .large or a small scale transform. If the question is "can I make it exactly 28 points with a different stroke," switch to a custom loader. Trying to force UIActivityIndicatorView into a role it was not designed for usually creates harder layout and styling problems later.

Common Pitfalls

  • Setting the spinner frame and expecting the rendered indicator to resize.
  • Applying a large transform and then wondering why nearby views overlap it.
  • Using a transformed spinner where the design really needs a custom animated view.
  • Ignoring platform differences between older indicator styles and the modern medium and large options.
  • Treating a visual scale hack as if it were a true intrinsic size change.

Summary

  • 'UIActivityIndicatorView supports a limited set of native sizes rather than arbitrary dimensions.'
  • The supported first choice is selecting the appropriate built-in style, usually medium or large.
  • 'CGAffineTransform can visually scale the spinner when you need a modest adjustment.'
  • Auto Layout does not automatically treat a scaled spinner as if its intrinsic size changed.
  • For exact visual control, build or adopt a custom loading indicator instead.

Course illustration
Course illustration

All Rights Reserved.