Toolkit
expo-arcgis-toolkit brings the components of the ArcGIS Maps SDK Toolkits
(Swift,
Kotlin) to expo-arcgis. Each component
is the Toolkit’s own native view, driven by your <Map> / <MapView> and <Scene> /
<SceneView>. The look and the behavior are Esri’s, and the props are the Toolkit’s settings, with
its names and defaults.
Install
Section titled “Install”npx expo install expo-arcgis expo-arcgis-toolkitIt builds on expo-arcgis: set that up first (Getting started). Then add this package’s config plugin after expo-arcgis’s, and regenerate the native projects:
module.exports = { expo: { plugins: [ ['expo-arcgis', { apiKey: process.env.ARCGIS_API_KEY }], 'expo-arcgis-toolkit', ], },};npx expo prebuild --cleanConfig plugin options
Section titled “Config plugin options”By default, the plugin adds:
- the iOS camera and microphone descriptions, for the feature form’s attachments and barcodes;
- for
OfflineMapAreas, the iOS background task identifiers and background fetch, and the Android download permissions. On Android 13+, request the notification permission at runtime to see the download progress.
| Option | What it does |
|---|---|
cameraUsageDescription, microphoneUsageDescription |
Your own wording for the descriptions; false leaves one out. |
offlineMapAreas: false |
Leaves out what OfflineMapAreas needs. |
jobManager: true |
Permits the background task of the job manager (jobManager, iOS). |
oAuthRedirectUris: ['my-app://auth'] |
Declares the Kotlin Toolkit’s AuthenticationActivity for these redirect URIs. Authenticator’s OAuth and IAP sign-ins need it on Android. Give them a scheme of their own, not the app’s scheme. |
ar: true |
What the augmented reality views need. On iOS, that is the camera and location descriptions. On Android, it is the camera and location permissions, plus ARCore’s entry. |
ar: { arcore: 'required' } |
Makes ARCore required, so Google Play shows the app on ARCore devices only. It is optional by default. |
ar: { arcoreApiKey } |
The Google Cloud API key for the world-scale view’s geospatial tracking. |
Components
Section titled “Components”| Component | Kind | iOS | Android | Sample |
|---|---|---|---|---|
Compass |
over a map or scene view | ✓ | ✓ | Compass and scalebar, Scene accessories |
Scalebar |
over a map view | ✓ | ✓ | Compass and scalebar |
OverviewMap |
over a map or scene view | ✓ | — | Overview map |
LocationButton |
over a map view | ✓ | — | Location button |
FloorFilter |
over a map or scene view (floor-aware data) | ✓ | ✓ | Floor filter |
BasemapGallery |
panel for a map | ✓ | ✓ | Basemap gallery |
Bookmarks |
panel for a map or scene view | ✓ | — | Bookmarks |
Legend |
panel for a map or scene view | — | ✓ | Legend |
Search |
panel for a map or scene view | ✓ | — | Search |
FloatingPanel |
panel with React content, floating over a map or scene view | ✓ | — | Floating panel |
BuildingExplorer |
panel for a local scene view | ✓ | — | Building explorer |
UtilityNetworkTrace |
panel for a map view (utility networks) | ✓ | ✓ | Utility network trace |
PopupView |
panel (a popup from identifyPopups) |
✓ | ✓ | Popup |
FeatureFormView |
panel (a feature from identify) |
✓ | ✓ | Feature form |
OfflineMapAreas |
panel for a web map (<Map portalItem>) |
✓ | ✓ | Offline map areas |
jobManager |
app-level: keeps long jobs across launches | ✓ | — | Job manager |
Authenticator |
app-level: prompts for authentication challenges | ✓ | ✓ | Authenticator |
TableTopSceneView |
augmented reality: the scene on a table | ✓ | ✓ | AR tabletop |
FlyoverSceneView |
augmented reality: fly over the scene | ✓ | ✓ | AR flyover |
WorldScaleSceneView |
augmented reality: the scene in the world around you | ✓ | ✓ | AR world scale |
A component that the Toolkit has on one platform only renders nothing on the other platform, and warns once in development. An API that one platform lacks does nothing there. The Platform differences page lists them, with the settings that differ.
Every component, prop and type is in the Toolkit API reference.
Where components go
Section titled “Where components go”Over a view. Compass, Scalebar, OverviewMap, LocationButton and FloorFilter go
inside the <MapView> or <SceneView>. The view draws them over the map at their alignment,
keeping its contentInsets clear.
Panels are views of their own, which you lay out:
- A panel for a map, such as
BasemapGallery, goes anywhere inside the<Map>. - A panel for a view, such as
Bookmarks,Legend,Search,BuildingExplorerorUtilityNetworkTrace, goes inside its<MapView>/<SceneView>, over the map. It can also go anywhere else, with the view’s ref as itsgeoView. PopupViewandFeatureFormViewshow whatidentifyPopupsandidentifyfound: pass the result’sref.
import { Map, MapView, type MapViewHandle } from 'expo-arcgis';import { Bookmarks, Compass, Scalebar } from 'expo-arcgis-toolkit';import { useRef } from 'react';
export default function App() { const mapView = useRef<MapViewHandle>(null); return ( <> <Map portalItem={{ itemId: '<web map id>' }}> <MapView ref={mapView} style={{ flex: 1 }}> <Compass /> <Scalebar units="metric" /> </MapView> </Map> {/* Outside the view: bound to it by its ref. */} <Bookmarks geoView={mapView} style={{ height: 240 }} /> </> );}Floating panel
Section titled “Floating panel”<FloatingPanel> shows your React content in the Toolkit’s floating panel (iOS). Inside a
<MapView> or <SceneView>, it floats over the view, and touches outside the panel reach the map.
The layout depends on the size class:
- In portrait, it rests at the bottom of the view, like a sheet.
- Elsewhere, it floats at the top, placed by
horizontalAlignmentand at mostmaxWidthwide.
The user drags its handle between the 'summary', 'half' and 'full' detents. The panel decides
the content’s size, and React lays the content out in it: give the content flex: 1 to fill it.
const [detent, setDetent] = useState<FloatingPanelDetent>('half');
<MapView style={{ flex: 1 }}> <FloatingPanel selectedDetent={detent} onSelectedDetentChange={setDetent}> <FlatList style={{ flex: 1 }} data={places} renderItem={renderPlace} /> </FloatingPanel></MapView>Authenticator
Section titled “Authenticator”<Authenticator> goes once at the root of the app. While it is mounted, it handles the
authentication challenges and shows the Toolkit’s prompts:
- a username and password, for token-secured services and IWA servers;
- the portal’s sign-in page, for a portal in
oAuthUserConfigurations; - the IAP sign-in, for a host in
iapConfigurations; - whether to trust an untrusted host, on iOS with
promptForUntrustedHosts; - which client certificate to use.
import { MapSettings, enablePersistentCredentialStore } from 'expo-arcgis';import { Authenticator } from 'expo-arcgis-toolkit';
enablePersistentCredentialStore(); // keeps the sign-ins across launches
export default function RootLayout() { return ( <MapSettings config={{ apiKey }}> <Stack /> <Authenticator oAuthUserConfigurations={[ { portalUrl: 'https://www.arcgis.com', clientId: '<client id>', redirectUrl: 'my-app://auth' }, ]} /> </MapSettings> );}It takes the place of expo-arcgis’s challenge handlers, and it hands the challenges back when it
unmounts. Its ref’s signOut() is the Toolkit’s sign-out: it revokes the OAuth tokens, signs out
of the IAPs and clears the credential stores.
On iOS, App Transport Security rejects an untrusted host before the SDK can ask. Allow the host in
Info.plist first (NSAppTransportSecurity › NSExceptionDomains), and keep Expo’s
NSAllowsLocalNetworking: the development build loads its JavaScript from the local network.
Augmented reality
Section titled “Augmented reality”TableTopSceneView, FlyoverSceneView and WorldScaleSceneView are expo-arcgis’s <SceneView>
shown in augmented reality: iOS uses ARKit, Android ARCore.
- Place one inside a
<Scene>. - Overlays go inside it, and its events (
onTap…) and ref (identify…) work as a scene view’s do. - The device’s movement controls the camera, so
cameraandcameraControllerdon’t apply.
For the camera feed to show through the scene, make the scene’s surface transparent. Tabletop and world-scale views also need a camera that can go below the surface:
import { Scene, SceneLayer } from 'expo-arcgis';import { TableTopSceneView } from 'expo-arcgis-toolkit';
<Scene surface={{ opacity: 0, navigationConstraint: 'unconstrained' }}> <SceneLayer url="<a 3D object scene service>" /> <TableTopSceneView anchorPoint={{ latitude: 45.5326, longitude: -122.6835 }} translationFactor={1000} clippingDistance={400} /></Scene>AR needs a device: the iOS simulator has no ARKit, and an Android emulator has no ARCore unless
Google Play Services for AR is installed. The Android views report why they failed to initialize
(onInitializationStatusChange).