Expo UI and Router for iOSExpo SDK 57 and later, iOS only
Components

ProgressView

A SwiftUI ProgressView component for displaying progress indicators.

Expo UI ProgressView matches the official SwiftUI ProgressView API and supports styling via the progressViewStyle modifier.

Usage

Note: When using the linear style (which is the default for determinate progress), ProgressView is a flexible-width component, it expands to fill available horizontal space. When using matchContents on the Host, you should apply a frame modifier on the ProgressView to give it an explicit width. Alternatively, give the Host an explicit size using style (for example, style={{ width: 300 }} or style={{ flex: 1 }}). The circular style and indeterminate spinner have a fixed size and work with matchContents.

Indeterminate progress

When no value is provided, the progress view displays an indeterminate indicator (spinner).

import { Host, ProgressView } from '@expo/ui/swift-ui';

export default function IndeterminateExample() {
  return (
    <Host matchContents>
      <ProgressView />
    </Host>
  );
}
An indeterminate spinner sized to its content at the leading edge
An indeterminate spinner sized to its content at the leading edge

Determinate progress

Provide a value between 0 and 1 to show determinate progress.

import { Host, ProgressView } from '@expo/ui/swift-ui';

export default function DeterminateExample() {
  return (
    <Host style={{ flex: 1 }}>
      <ProgressView value={0.5} />
    </Host>
  );
}
A linear progress bar filled to the halfway point
A linear progress bar filled to the halfway point

Progress view styles

Use the progressViewStyle modifier to change the progress view's appearance. Available styles are: automatic, linear, and circular.

import {
  Host,
  ProgressView,
  Text,
  VStack,
} from '@expo/ui/swift-ui';
import { progressViewStyle } from '@expo/ui/swift-ui/modifiers';

export default function ProgressViewStylesExample() {
  return (
    <Host style={{ flex: 1 }}>
      <VStack spacing={16}>
        <Text>Linear</Text>
        <ProgressView
          value={0.5}
          modifiers={[progressViewStyle('linear')]}
        />
        <Text>Circular</Text>
        <ProgressView
          value={0.5}
          modifiers={[progressViewStyle('circular')]}
        />
      </VStack>
    </Host>
  );
}
A half-filled linear progress bar labelled Linear, above a circular spinner labelled Circular
A half-filled linear progress bar labelled Linear, above a circular spinner labelled Circular

With label

You can pass custom components as children to provide a label for the progress view.

import { Host, ProgressView, Text } from '@expo/ui/swift-ui';

export default function LabelExample() {
  return (
    <Host style={{ flex: 1 }}>
      <ProgressView value={0.25}>
        <Text>Loading...</Text>
      </ProgressView>
    </Host>
  );
}
A progress bar filled to one quarter, with the label Loading above it
A progress bar filled to one quarter, with the label Loading above it

Tinted progress view

Use the tint modifier to change the progress view's color.

import { Host, ProgressView } from '@expo/ui/swift-ui';
import { tint } from '@expo/ui/swift-ui/modifiers';

export default function TintedExample() {
  return (
    <Host style={{ flex: 1 }}>
      <ProgressView value={0.7} modifiers={[tint('red')]} />
    </Host>
  );
}
A red progress bar filled to roughly seventy percent
A red progress bar filled to roughly seventy percent

Timer-based progress

Use the timerInterval prop to create a progress view that automatically animates over a time range. This is useful for showing countdown timers or timed operations.

Note: Timer-based progress is only available on iOS 16+ and tvOS 16+.

import {
  Host,
  ProgressView,
  Text,
  VStack,
} from '@expo/ui/swift-ui';

export default function TimerExample() {
  const startDate = new Date();
  const endDate = new Date(Date.now() + 10000); // 10 seconds from now

  return (
    <Host style={{ flex: 1 }}>
      <VStack spacing={16}>
        <ProgressView
          timerInterval={{ lower: startDate, upper: endDate }}
        />
        <ProgressView
          timerInterval={{ lower: startDate, upper: endDate }}
          countsDown={false}>
          <Text>Counting up</Text>
        </ProgressView>
      </VStack>
    </Host>
  );
}
Two timer progress bars part way through a ten second range, one labeled Counting up
Two timer progress bars part way through a ten second range, one labeled Counting up

API

import { ProgressView } from '@expo/ui/swift-ui';

Component

ProgressView

Type: React.Element<ProgressViewProps>

Renders a SwiftUI ProgressView component.

ProgressViewProps

children

Optional • Type: ReactNode

A label describing the progress view's purpose.

countsDown

iOS 16+

Optional • Type: boolean • Default: true

A Boolean value that determines whether the view empties or fills as time passes. If true, which is the default, the view empties.

timerInterval

iOS 16+

Optional • Type: ClosedRangeDate

The lower and upper bounds for automatic timer progress.

value

Optional • Literal type: union

The current progress value. A value between 0 and 1. When undefined, the progress view displays an indeterminate indicator.

Acceptable values are: number | null

Inherited props

Modifiers

Use these modifiers in the modifiers prop of the SwiftUI version.

Expo UI lets you put any of the 89 modifiers for any view on ProgressView, but not all of them do something here.

  • 67 change what you see on ProgressView.
  • 1 work, but not in the way that you may expect.
  • 9 have no visible effect on ProgressView.
  • 13 work only in one place, such as a widget or a Grid.

Best modifiers for ProgressView

These modifiers are made for ProgressView, or they are the ones that you use most with it.

Also works on ProgressView

ProgressView takes these modifiers too, and each one works in the usual way.

Needs care on ProgressView

These modifiers work on ProgressView, but not in the way that you may expect.

ModifierWhat to know
animationThe bar animates its own progress. Use this for the other modifiers on the view.

No visible effect on ProgressView

ProgressView accepts these modifiers, but you see no change. They do not give an error.

ModifierWhy nothing happens
accessibilityElementIt joins the child views into one accessibility element, and ProgressView takes no child views.
containerShapeIt sets the shape that the child views use for containerRelativeShape, and ProgressView takes no child views.
contentShapeIt changes the area that gets touches, and ProgressView gets no touches of its own.
geometryGroup iOS 17+It works on the child views that you give the component, and ProgressView takes none.
imageScaleIt changes only SF Symbols, and ProgressView shows none.
layoutPriorityIt has an effect only when the view shares an axis with other views in a stack.
onLongPressGestureIn SDK 57, ProgressView does not send modifier events to JavaScript, so the handler does not run.
onTapGestureIn SDK 57, ProgressView does not send modifier events to JavaScript, so the handler does not run.
zIndexIt changes the order of views that cover each other in the same parent, and ProgressView does not stack its children.

Only in some places

These modifiers work only in a widget, in a Grid, in a Namespace or in a parent that asks for them.

ModifierWhere it works
activityBackgroundTintWorks only in a Live Activity. It has no effect in the app.
alignmentGuideHas an effect only when the parent, such as a VStack or ZStack, aligns its children by the same guide.
containerBackgroundWorks only in a widget, or in a navigation container when you use a navigation placement.
glassEffectIdWorks only on a view that also has glassEffect, in a GlassEffectContainer and a Namespace.
gridCellAnchor iOS 16+Works only on a cell of a Grid. Grid is in @expo/ui/swift-ui, but it has no Expo docs page.
gridCellColumnsWorks only on a view in a Grid.Row. Grid is in @expo/ui/swift-ui, but it has no Expo docs page.
gridCellUnsizedAxesWorks only on a view in a Grid. Grid is in @expo/ui/swift-ui, but it has no Expo docs page.
gridColumnAlignment iOS 16+Works only on a view in a Grid.Row. Grid is in @expo/ui/swift-ui, but it has no Expo docs page.
invalidatableContent iOS 17+Has an effect only when a parent view uses redacted with the invalidated reason.
matchedGeometryEffectWorks only in a Namespace. Give two views the same id and change between them with an animation.
privacySensitiveHas an effect only when a parent view uses redacted with the privacy reason.
unredactedHas an effect only in a parent view that uses redacted.
widgetURLWorks only in a widget. It has no effect in the app.

Sources

The original Expo docs for this page:

On this page