From d9819136031cc24923ec2784ed430122e7ab5b63 Mon Sep 17 00:00:00 2001 From: dimadesu Date: Sat, 7 Feb 2026 15:07:05 +1100 Subject: [PATCH] Fix slider crash on cameras with ultra-wide zoom (< 1.0x) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add binding adapter that sets slider range before value to prevent IllegalStateException when camera reports zoom ratio below the slider's default minimum. The adapter intercepts all three slider attributes (value, valueFrom, valueTo) and sets them in the correct order, avoiding the race condition where data binding could set value before the range was updated. Fixes crash: "Slider value(0.6) must be greater or equal to valueFrom(1.0)" --- The Issue (High Level) The Slider widget crashes when its value is outside the [valueFrom, valueTo] range at draw time. The race condition: - Camera with ultra-wide lens is selected (zoom range: 0.6x - 8.0x) - The camera reports current zoom = 0.6x - Data binding updates fire, but in the wrong order: - zoomRatio → 0.6 (but slider still has default range 1.0-8.0) - zoomRatioRange → [0.6, 8.0] (too late!) - Slider tries to draw with value=0.6, min=1.0 → CRASH --- .../lifestreamer/ui/BindingAdapters.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/app/src/main/java/com/dimadesu/lifestreamer/ui/BindingAdapters.kt b/app/src/main/java/com/dimadesu/lifestreamer/ui/BindingAdapters.kt index 131d26d..06230f3 100644 --- a/app/src/main/java/com/dimadesu/lifestreamer/ui/BindingAdapters.kt +++ b/app/src/main/java/com/dimadesu/lifestreamer/ui/BindingAdapters.kt @@ -37,4 +37,41 @@ fun setSliderListeners(slider: Slider, attrChange: InverseBindingListener) { slider.addOnChangeListener { _, _, _ -> attrChange.onChange() } +} + +/** + * Custom binding adapter that sets slider value, valueFrom, and valueTo together + * to avoid crashes when the value is outside the default range. + * + * This is needed because cameras with ultra-wide lenses can have zoom ratios < 1.0, + * but the slider's default valueFrom is often 1.0, causing a crash when the value + * is set before the range is updated. + * + * Handles both Float and Integer (Number) values. + */ +@BindingAdapter("android:value", "android:valueFrom", "android:valueTo", requireAll = true) +fun setSliderValueWithRange(slider: Slider, value: Number?, valueFrom: Number?, valueTo: Number?) { + // Skip if any value is null (not yet initialized) + if (value == null || valueFrom == null || valueTo == null) return + + val floatValue = value.toFloat() + val floatFrom = valueFrom.toFloat() + val floatTo = valueTo.toFloat() + + // Skip if range is invalid + if (floatFrom >= floatTo) return + + // Set range first (before value) + if (slider.valueFrom != floatFrom) { + slider.valueFrom = floatFrom + } + if (slider.valueTo != floatTo) { + slider.valueTo = floatTo + } + + // Clamp value to valid range and set it + val clampedValue = floatValue.coerceIn(floatFrom, floatTo) + if (slider.value != clampedValue) { + slider.value = clampedValue + } } \ No newline at end of file