Petnow LogoPetnow

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:

  1. Build the surrounding UI yourself — Place status/progress text, buttons, and so on outside of CameraView as regular Views/Compose, and drive them with the listener and getState()
  2. Floating guide — Inject a guide view that moves along with the tracker (setFloatingGuide)
  3. 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 = false

Next Steps

Once you've learned how to customize the UI, refer to the following documentation:

On this page