From cce6f94387bd0bf28cc920639d8dc4e5ac02a12a Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Wed, 18 Feb 2026 20:58:30 +0000
Subject: [PATCH] feat(a11y): improve dynamic metrics and interaction feedback
- Add dynamic content descriptions for bitrate and frame time metrics
- Add content description to camera viewfinder
- Add haptic feedback to IP address copy action
- Fix duplicate XML attributes in fragment_camera.xml preventing build
Co-authored-by: manupawickramasinghe <73810867+manupawickramasinghe@users.noreply.github.com>
---
.Jules/palette.md | 3 +++
.../com/samsung/android/scan3d/fragments/CameraFragment.kt | 6 ++++++
app/src/main/res/layout/fragment_camera.xml | 6 +-----
app/src/main/res/values/strings.xml | 5 +++++
4 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/.Jules/palette.md b/.Jules/palette.md
index a34c9ff..4649155 100644
--- a/.Jules/palette.md
+++ b/.Jules/palette.md
@@ -20,3 +20,6 @@
## 2025-10-21 - Destructive Action Confirmation
**Learning:** The "STOP" button terminated the camera stream and app immediately without confirmation, posing a risk of accidental interruption.
**Action:** Always wrap destructive actions (like stopping a server or deleting data) in a confirmation dialog (e.g., `AlertDialog`) to prevent data loss or unintended service stoppage.
+## 2024-05-23 - [Dynamic Metric Accessibility]
+**Learning:** Dense technical metrics (like '33ms' or '500kB/s') in tight layouts are often inaccessible to screen readers because they lack context labels. Adding visible labels would break the layout.
+**Action:** Use programmatic `contentDescription` updates in the data binding loop (e.g., 'Frame time: 33 milliseconds') to provide rich context to screen readers without altering the visual design.
diff --git a/app/src/main/java/com/samsung/android/scan3d/fragments/CameraFragment.kt b/app/src/main/java/com/samsung/android/scan3d/fragments/CameraFragment.kt
index 2385d99..20df73e 100644
--- a/app/src/main/java/com/samsung/android/scan3d/fragments/CameraFragment.kt
+++ b/app/src/main/java/com/samsung/android/scan3d/fragments/CameraFragment.kt
@@ -88,6 +88,8 @@ class CameraFragment : Fragment() {
binding.textView6.setOnClickListener {
// Copy the ip address to the clipboard
ClipboardUtil.copyToClipboard(context, "ip", binding.textView6.text.toString())
+ // Perform haptic feedback
+ binding.textView6.performHapticFeedback(android.view.HapticFeedbackConstants.CONTEXT_CLICK)
// Toast to notify the user
Toast.makeText(context, "Copied to clipboard", Toast.LENGTH_SHORT).show()
}
@@ -108,8 +110,12 @@ class CameraFragment : Fragment() {
// Stuff that updates the UI
fragmentCameraBinding.qualFeedback?.text =
" " + this.rateKbs + "kB/sec"
+ fragmentCameraBinding.qualFeedback?.contentDescription =
+ getString(R.string.bitrate_description_template, this.rateKbs)
fragmentCameraBinding.ftFeedback?.text =
" " + this.ms + "ms"
+ fragmentCameraBinding.ftFeedback?.contentDescription =
+ getString(R.string.frametime_description_template, this.ms)
})
}
diff --git a/app/src/main/res/layout/fragment_camera.xml b/app/src/main/res/layout/fragment_camera.xml
index 7eeaa62..70764ad 100644
--- a/app/src/main/res/layout/fragment_camera.xml
+++ b/app/src/main/res/layout/fragment_camera.xml
@@ -33,6 +33,7 @@
android:id="@+id/view_finder"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:contentDescription="@string/camera_preview_description"
android:layout_gravity="center"
android:layout_weight="1" />
@@ -101,7 +102,6 @@
android:layout_marginTop="0pt"
android:layout_marginBottom="4pt"
android:background="#FFAA00"
- android:importantForAccessibility="no"
android:paddingTop="5pt" />
@@ -158,7 +158,6 @@
android:layout_height="wrap_content"
android:labelFor="@+id/spinnerEncoding"
android:text="@string/encoding_label"
- android:labelFor="@+id/spinnerEncoding"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
This will stop the camera stream and close the application.
Stop
Cancel
+
+
+ Camera viewfinder
+ Bitrate: %1$d kilobytes per second
+ Frame time: %1$d milliseconds