`TrackedMovementView`
The drop-in widget that bundles camera + pose detection + tracking
into one mountable surface. Most consumers use this; only reach for
MovementTracker + PoseCameraView manually when you need a custom
layout (e.g. a non-camera pose source like recorded video).
TrackedMovementView( cameras: cameras, movement: myMovement, onRepCompleted: (event) => …, onTrackingResult: (result) => …,)Constructor
const TrackedMovementView({ required List<CameraDescription> cameras, required Movement movement, MovementConfig? movementConfig, MovementTrackerPreset? preset, MovementTrackerConfig? config, OnTrackingResult? onTrackingResult, OnRepCompleted? onRepCompleted, OnPositionChange? onPositionChange, OnFormFeedback? onFormFeedback, VoidCallback? onReady, void Function(String error)? onError, Widget? overlay, Widget Function(BuildContext, TrackedMovementState)? overlayBuilder, bool showSkeleton = true, bool showControls = false, int? initialCameraIndex, Widget? loadingWidget, ResolutionPreset resolutionPreset = ResolutionPreset.medium, bool pipelined = true, BlazeFlowBackend? backend, ExecutionConfig? executionConfig, int isolateCount = 1, bool syncedFrameMode = false, int displayFrameMaxDimension = 480, bool preferCpu = false,});Required
cameras | From await availableCameras(). |
movement | The loaded Movement. |
Optional
movementConfig | A CMS-published MovementConfig overlay. When present, its trackingPoints / phases / formRules override the inline values from the .pose file. |
preset | One of casual, standard, strict, competition. Mutually exclusive with config. |
config | A full MovementTrackerConfig. Takes precedence over preset. |
showSkeleton | Draw the pose skeleton overlay. Default true. |
showControls | Show camera-switch + flash controls. Default false. |
initialCameraIndex | Which camera to start with. Default 0 (usually rear; pick the front-facing index for selfie mode). |
resolutionPreset | Camera capture preset. Default medium (~720p). |
pipelined | Double-buffered pose inference. Default true. |
backend | Hardware backend for the pose engine. Null = auto-select. |
executionConfig | Full PoseFlow’s native runtime execution config. Overrides backend. |
isolateCount | Background isolates for inference. 1 by default; bump to 2-4 on multi-core targets if you need higher FPS. |
syncedFrameMode | Display the processed frame instead of the live preview. Eliminates skeleton/image lag at the cost of ~1 frame of latency. |
preferCpu | Force the CPU backend on Android even when NNAPI is available. |
Callbacks
typedef OnTrackingResult = void Function(TrackingResult result);typedef OnRepCompleted = void Function(RepCompletedEvent event);typedef OnPositionChange = void Function(PositionChangeEvent event);typedef OnFormFeedback = void Function(FormFeedbackEvent event);onTrackingResult fires every frame, use it for live HUD updates
(form score badge, current phase indicator, etc.).
onRepCompleted fires once per completed rep, use it for the rep
counter, audio beep, haptic feedback.
onFormFeedback fires per form-cue event, use it for the toast
deck, audio cue, vibration burst.
onPositionChange fires when the vector matcher’s committed
position label changes, useful for “you’re in the down position”
type cues.
Overlay options
Two ways to draw on top of the camera + skeleton:
overlay, a static Widget painted above the skeleton:
TrackedMovementView( ... overlay: const Center(child: Text('Squat in front of the camera')),)overlayBuilder, receives the current TrackedMovementState
on every rebuild:
TrackedMovementView( ... overlayBuilder: (context, state) { return Positioned( top: 60, left: 24, child: Text('Reps: ${state.repCount}'), ); },)TrackedMovementState
The widget’s externally-visible state, exposed via the builder:
class TrackedMovementState { final TrackingResult? result; final int repCount; final double formScore; final String? position; final RepQuality? lastRepQuality; final bool isTracking; final List<String> activeFeedback; final List<RepCompletedEvent> recentReps; // last 5}Imperative methods
The widget exposes a GlobalKey<TrackedMovementViewState> if you
need to drive it from outside:
final key = GlobalKey<TrackedMovementViewState>();
TrackedMovementView(key: key, ...)
// Later:key.currentState?.reset(); // start a new setkey.currentState?.pause();key.currentState?.resume();Under the hood
TrackedMovementView internally builds args via
LoadMovementArgs.from(...).applyTo(tracker).
Same convention as every other consumer. There is no magic
involved, you could reproduce its behaviour by mounting
PoseCameraView + a MovementTracker
yourself; the widget just bundles them so the common case is one
line.
Read next
MovementTracker, the underlying orchestrator.LoadMovementArgs.PoseCameraView, the camera primitiveTrackedMovementViewwraps.- Rep counting parity across surfaces.