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