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