Android 0.3.4 publishes the complete native picker as two aligned Maven
artifacts. seatlayer-android contains the raw API and headless
contract; seatlayer-android-compose contains the ready-made adaptive picker,
native components, customization layers, and View/XML host.
implementation("io.seatlayer:seatlayer-android:0.3.4")
implementation("io.seatlayer:seatlayer-android-compose:0.3.4")Application and SDK ownership
| Native Android UI owns | SeatLayer SDK owns |
|---|---|
| Header, price/floor/section navigation, accessibility filters, confirmation, tiers, quantities, cart, hold state, checkout, loading/errors, Test Mode, attribution and Back | Seats, labels, geometry, hit testing, pan/pinch, venue camera, authored 3D, and panorama pixels |
| Compose/View hierarchy, TalkBack, 48dp targets, predictive Back, safe areas, lifecycle and haptics | Authoritative inventory state and supported map capabilities |
The SDK presents one native confirmation, cart, Test Mode indicator, and checkout action around the venue surface.
Integration ladder
| Path | API | Host ownership |
|---|---|---|
| Ready Compose | SeatLayerPicker |
Configuration, callbacks, destination |
| Branded Compose | Theme, strings, options, styles, builders | Brand or selected complete parts |
| Custom Compose | SeatLayerPickerScope + public composables |
Entire Compose hierarchy |
| Ready View/XML | SeatLayerPickerView |
Existing View screen and dismissal |
| Custom Views | SeatLayerPickerStateHolder + SeatLayerPickerMapView |
Entire Android View hierarchy |
| Raw map | SeatLayerView |
Every buyer surface and hold transition |
The first five paths retain the same read-only picker state, typed controller, ordered actions, supported-feature checks, lifecycle recovery, and checkout handoff.
Customize the ready-made picker
Three layers can be mixed without forking the SDK:
SeatLayerPickerOptions,SeatLayerPickerTheme, localizedSeatLayerPickerStrings, andSeatLayerPickerStyleschange behavior and appearance.SeatLayerPickerBuildersdecorates or replaces any of 25 independent complete parts.SeatLayerPickerScopeand the public components create a host-owned Compose hierarchy.
SeatLayerPicker(
configuration = configuration,
themeMode = SeatLayerPickerThemeMode.Auto,
options = SeatLayerPickerOptions(
layout = SeatLayerPickerLayoutMode.Adaptive,
haptics = true,
),
strings = SeatLayerPickerStrings.localized("fr-FR"),
styles = SeatLayerPickerStyles(
parts = mapOf(
SeatLayerPickerPart.CheckoutBar to SeatLayerPickerPartStyle(
cornerRadius = 18.dp,
),
),
),
builders = SeatLayerPickerBuilders(
header = { _, defaultContent -> defaultContent() },
),
onCheckout = ::openCheckout,
)Each builder receives SeatLayerPickerPartContext: read-only picker state,
native presentation state, typed controller, resolved theme, strings,
options, global styles, and the style for that part. Its second closure argument
renders the default content; calling it decorates the stock component, while
omitting it replaces only that part.
Test Mode and attribution intentionally remain outside the replacement matrix.
Compose a custom screen
SeatLayerPickerScope(
configuration = configuration,
callbacks = SeatLayerPickerCallbacks(
onCheckout = ::openCheckout,
onClose = onClose,
),
) {
SeatLayerPickerLifecycle()
SeatLayerPickerBackHandler()
SeatLayerPickerHapticEffects()
Column(Modifier.fillMaxSize()) {
SeatLayerPickerHeader(onClose)
SeatLayerPriceLegend()
Box(Modifier.weight(1f)) {
SeatLayerPickerMap(Modifier.fillMaxSize())
SeatLayerPickerMapControls()
SeatLayerConfirmCard()
}
SeatLayerPickerCartSheet()
}
}The scope owns one picker state. Do not place a second map in another adaptive branch; the layout moves the existing map between compact and wide containers so camera, cart, and hold state survive rotation or window resize.
View/XML and custom Views
SeatLayerPickerView hosts the ready-made tree in a traditional View screen:
binding.picker.bind(
lifecycleOwner = this,
configuration = configuration,
onCheckout = ::openCheckout,
onReady = ::observeReady,
onSnapshot = ::observeSnapshot,
onClose = ::finish,
)For fully custom Views:
- Create one
SeatLayerPickerStateHolderfor the screen lifecycle. - Bind one
SeatLayerPickerMapViewto it. - Collect
state, an immutableStateFlowprojection. - Invoke semantic actions through
stateHolder.controller. - Reproduce lifecycle, Back, Test Mode, attribution, and safe-area duties the ready host normally supplies.
Public component catalogue
| Builder part | Stock public components |
|---|---|
| Header and navigation | SeatLayerPickerHeader, price legend, floor selector/strip, section navigator, dock bar |
| Map and controls | SeatLayerPickerMap, map controls, zoom controls, accessibility filters |
| Decisions | Best-seats form, seat confirmation, tier selector/choices, confirm card, GA/table prompts |
| Cart and holds | Cart list/sheet, countdown, lapse notice, undo notice, checkout bar/button |
| Immersive views | SeatLayerVenue3D, SeatLayerSeatViewChrome |
| System states | Loading, retryable/fatal error, empty/sold-out/sales-closed, action error |
| Truth components | Test Mode indicator and required attribution |
All stock controls expose TalkBack labels, roles, enabled/disabled state, and at least 48dp interaction targets. Adaptive compact/wide layout, large text, RTL, safe drawing, and gesture insets remain SDK responsibilities unless a custom host replaces the whole hierarchy.
Headless state guarantees
SeatLayerPickerStateHolder.state combines read-only SeatLayer state with
native presentation state. The controller provides ordered
suspending actions for selection, filters, floors/sections, view modes, camera,
GA/tables, holds, best available, lifecycle refresh, checkout, undo, Back, and
close.
- Published state always belongs to the configured Event and supersedes older state.
- Malformed optional fields are ignored; invalid schema/session/event identity is rejected.
- Empty UI appears only from affirmative sold-out/all-unavailable truth.
- Optional commands are sent only when the exact capability is advertised.
- Repeated checkout taps join one flight.
Custom UI never mutates SDK-owned picker state locally.
Selection, cart, and checkout
The confirmation surface keeps a seat pending until the buyer accepts it. When
event-authored tiers exist, confirmPending(tierId) applies the exact tier
before confirmation, so cart and checkout never briefly carry the wrong price.
GA and variable-table prompts validate quantity against authoritative capacity and occupancy. Seats, GA, and tables enter one dense cart. Removing a line opens a session-scoped undo window only while that exact line remains absent.
Checkout returns one SeatLayerPickerCheckoutHandoff with opaque holdId,
server expiry, currency, priced lines, and display total. Ordinary state omits
holdId. Your backend must inspect the hold and calculate payment from server
data.
Lifecycle, Back, and recovery
The ready picker refreshes availability when supported, reconciles server hold state, reports lost seats, and presents one recoverable hold-lapse message on foreground or return from checkout.
Back closes the most local state first: quantity prompt → expanded cart → panorama → venue 3D → confirmation → focused section → host route. Custom Compose hosts install the exported lifecycle/Back/haptic effects; custom View hosts provide equivalent behavior around the same controller.
Activity/process recreation creates a new session. Restore only a host-owned
hold through initialHoldId and the same access provider, then let SeatLayer
prove whether it is still active.
Optional picker prewarm
lifecycleScope.launch {
val result = SeatLayerPickerPrewarmer.prewarm(applicationContext)
check(result.engineStarted)
}Prewarm prepares the picker without receiving an Activity, event, credential, or hold and never starts a buyer session.
Test Mode and required attribution
Custom hosts must present Test Mode from authoritative Event state and show bottom-right attribution exactly when the SDK requires it. Server white-label entitlement is the only authority that disables attribution.
Production checklist
- Pin both Maven artifacts to
0.3.4. - Test every supported Android API level.
- Exercise ready/custom Compose and View paths your product uses.
- Validate TalkBack, 48dp targets, large text, RTL, safe areas, predictive Back, rotation, split-screen, process restoration, and picker load failure.
- Test real tiers, GA/tables, lapse recovery, 3D/panorama, rejected checkout, Test Mode, and attribution on physical devices.
- Confirm the trusted backend inspects and books the handoff hold.
Product scope
The picker selects one Event. It does not accept native Performance Group or Season configuration.