Fix clock preview when changin clock size

There are cases that when changing clock sizes, the clock preview
appears wrongly. This is due to that we resue the clock view and do
config changes to the view while they are in the clock carousel.

We need to always reset it to the original config when getting the
view again.

Test: See bug. Manually tested that the preview shows correctly
Bug: 286012668
Change-Id: Ib8a464d1affda67cf8756ae8526d4b6301e6ff5e
diff --git a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
index 053ac55..4f4bd1b 100644
--- a/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
+++ b/src/com/android/customization/picker/clock/ui/binder/ClockSettingsBinder.kt
@@ -176,23 +176,23 @@
                             ::Pair,
                         )
                         .collect { (clockId, size) ->
-                            val clockView =
-                                if (size == ClockSize.DYNAMIC) {
-                                    clockViewFactory.getLargeView(clockId)
-                                } else {
-                                    clockViewFactory.getSmallView(clockId)
-                                }
-                            (clockView.parent as? ViewGroup)?.removeView(clockView)
                             clockHostView.removeAllViews()
+                            val clockView =
+                                when (size) {
+                                    ClockSize.DYNAMIC -> clockViewFactory.getLargeView(clockId)
+                                    ClockSize.SMALL -> clockViewFactory.getSmallView(clockId)
+                                }
+                            // The clock view might still be attached to an existing parent. Detach
+                            // before adding to another parent.
+                            (clockView.parent as? ViewGroup)?.removeView(clockView)
                             clockHostView.addView(clockView)
-
                             when (size) {
                                 ClockSize.DYNAMIC -> {
                                     sizeOptions.radioButtonDynamic.isChecked = true
                                     sizeOptions.radioButtonSmall.isChecked = false
                                     clockHostView.doOnPreDraw {
-                                        it.pivotX = (it.width / 2).toFloat()
-                                        it.pivotY = (it.height / 2).toFloat()
+                                        it.pivotX = it.width / 2F
+                                        it.pivotY = it.height / 2F
                                     }
                                 }
                                 ClockSize.SMALL -> {
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
index c856112..56d4dea 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
@@ -48,8 +48,8 @@
     private lateinit var clockViewFactory: ClockViewFactory
     private var toCenterClockController: ClockController? = null
     private var offCenterClockController: ClockController? = null
-    private var toCenterClockView: View? = null
-    private var offCenterClockView: View? = null
+    private var toCenterClockScaleView: View? = null
+    private var offCenterClockScaleView: View? = null
     private var toCenterClockHostView: ClockHostView? = null
     private var offCenterClockHostView: ClockHostView? = null
     private var toCenterCardView: View? = null
@@ -125,8 +125,8 @@
                     val scalingUpClockId = adapter.clockIds[scalingUpIdx]
                     offCenterClockController = clockViewFactory.getController(scalingDownClockId)
                     toCenterClockController = clockViewFactory.getController(scalingUpClockId)
-                    offCenterClockView = motionLayout.findViewById(R.id.clock_scale_view_2)
-                    toCenterClockView =
+                    offCenterClockScaleView = motionLayout.findViewById(R.id.clock_scale_view_2)
+                    toCenterClockScaleView =
                         motionLayout.findViewById(
                             if (endId == R.id.next) R.id.clock_scale_view_3
                             else R.id.clock_scale_view_1
@@ -166,10 +166,10 @@
                         ?.onPickerCarouselSwiping(progress)
                     val scalingDownScale = getScalingDownScale(progress)
                     val scalingUpScale = getScalingUpScale(progress)
-                    offCenterClockView?.scaleX = scalingDownScale
-                    offCenterClockView?.scaleY = scalingDownScale
-                    toCenterClockView?.scaleX = scalingUpScale
-                    toCenterClockView?.scaleY = scalingUpScale
+                    offCenterClockScaleView?.scaleX = scalingDownScale
+                    offCenterClockScaleView?.scaleY = scalingDownScale
+                    toCenterClockScaleView?.scaleX = scalingUpScale
+                    toCenterClockScaleView?.scaleY = scalingUpScale
                 }
 
                 private fun onSmallClockViewTransition(progress: Float) {
@@ -339,6 +339,7 @@
                         isMiddleView,
                         clockScaleView,
                         clockId,
+                        clockHostView,
                     )
                 ClockSize.SMALL ->
                     initializeSmallClockView(
@@ -354,7 +355,12 @@
             isMiddleView: Boolean,
             clockScaleView: View,
             clockId: String,
+            clockHostView: ClockHostView,
         ) {
+            clockHostView.doOnPreDraw {
+                it.pivotX = it.width / 2F
+                it.pivotY = it.height / 2F
+            }
             if (isMiddleView) {
                 clockScaleView.scaleX = 1f
                 clockScaleView.scaleY = 1f
diff --git a/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt b/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
index 3d490d4..0dcd88b 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockViewFactory.kt
@@ -53,16 +53,31 @@
             ?: initClockController(clockId).also { clockControllers[clockId] = it }
     }
 
+    /**
+     * Reset the large view to its initial state when getting the view. This is because some view
+     * configs, e.g. animation state, might change during the reuse of the clock view in the app.
+     */
     fun getLargeView(clockId: String): View {
-        return getController(clockId).largeClock.view
+        return getController(clockId).largeClock.let {
+            it.animations.onPickerCarouselSwiping(1F)
+            it.view
+        }
     }
 
+    /**
+     * Reset the small view to its initial state when getting the view. This is because some view
+     * configs, e.g. translation X, might change during the reuse of the clock view in the app.
+     */
     fun getSmallView(clockId: String): View {
-        return smallClockFrames[clockId]
-            ?: createSmallClockFrame().also {
-                it.addView(getController(clockId).smallClock.view)
-                smallClockFrames[clockId] = it
-            }
+        val smallClockFrame =
+            smallClockFrames[clockId]
+                ?: createSmallClockFrame().also {
+                    it.addView(getController(clockId).smallClock.view)
+                    smallClockFrames[clockId] = it
+                }
+        smallClockFrame.translationX = 0F
+        smallClockFrame.translationY = 0F
+        return smallClockFrame
     }
 
     private fun createSmallClockFrame(): FrameLayout {