UI Customization
How to customize the CameraView guide UI and tracking display.
Before starting this guide, complete Basic Usage.
Overview
CameraView draws the preview and the default tracking UI. On top of it, you can customize the following:
- Build the surrounding UI yourself — Place status/progress text, buttons, and so on outside of
CameraViewas regular Views/Compose, and drive them with the listener andgetState() - Floating guide — Inject a guide view that moves along with the tracker (
setFloatingGuide) - Toggle the tracking display — Whether to show the default nose tracking UI (
isDogNoseTrackingUiEnabled)
The approach of injecting a custom overlay layout on top of the default tracking UI (provideCustomOverlayLayout, etc.) is exclusive to PetnowCameraFragment. For that approach, see Fragment Method (Legacy). To draw 100% of the tracking UI yourself, use Fully Custom UI.
Build the Surrounding UI Yourself
Since CameraView is only responsible for the preview area, you can place status text, progress bars, buttons, and so on as regular layouts above or around it, and update them via the detection callbacks.
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<io.petnow.ui.CameraView
android:id="@+id/camera_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Custom UI placed on top of CameraView -->
<TextView
android:id="@+id/status_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|center_horizontal"
android:layout_marginTop="48dp"
android:textColor="#FFFFFF" />
<ProgressBar
android:id="@+id/detection_progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_gravity="bottom" />
</FrameLayout>controller.setDetectionListenerV2(object : PetnowCameraDetectionListenerV2 {
override fun onDetectionStatus(primaryDetectionStatus: DetectionStatus) {
binding.statusText.text = when (primaryDetectionStatus) {
DetectionStatus.NoObject -> "Align your pet's face in the frame"
DetectionStatus.Detected -> "Nose print scans are coming through!"
is DetectionStatus.Failed -> when (primaryDetectionStatus.reason) {
DetectionFailureReason.TooClose -> "It's too close! Move back a bit."
DetectionFailureReason.TooFarAway -> "It's too far! Move closer."
DetectionFailureReason.TooDark -> "It's too dark! Try a brighter place."
else -> "Adjust your pet's pose"
}
else -> ""
}
}
override fun onDetectionProgress(progress: Int) {
binding.detectionProgress.progress = progress
}
override fun onDetectionFinished(result: CameraResult) { /* ... */ }
})Floating Guide (A Guide That Follows the Tracker)
Inject a guide view that moves along with the tracking area using setFloatingGuide(). CameraView automatically handles the coordinate and position calculations.
val guide = layoutInflater.inflate(R.layout.layout_floating_guide, cameraView, false)
cameraView.setFloatingGuide(guide)
// Control visibility and text yourself, in line with the detection status
val message = guide.findViewById<TextView>(R.id.text_guide_message)
message.text = "Point the nose straight at the camera"The guide view is placed with WRAP_CONTENT by default. Update its visibility and content from your app in line with the detection status (onDetectionStatus or getState()). To remove it, call setFloatingGuide(null).
Toggling the Tracking UI Display
To turn off the default nose tracking display, set isDogNoseTrackingUiEnabled to false (useful when you draw the tracking UI yourself).
cameraView.isDogNoseTrackingUiEnabled = falseNext Steps
Once you've learned how to customize the UI, refer to the following documentation:
- Fully Custom UI - Implement 100% of the tracking UI yourself
- Sound Guide - Sound playback settings
- Fragment Method (Legacy) - The Fragment overlay layout injection approach