Introduce clock carousel card

Added a clock carousel card in the back of each carousel item.
The card goes alpha 0 when in the center.
The card does not scale.

Test: https://drive.google.com/file/d/1eoksYlKaAYLLowyd65Sdpo29jjCZ3rBK/view?usp=sharing&resourcekey=0-Z5t4U0rWk-2WRcgc-a2KMw
Fixes: 276947242
Change-Id: I897a247ae0091ac08806a41dab2555bbc36ae0e5
diff --git a/res/drawable/carousel_item_card_background.xml b/res/drawable/carousel_item_card_background.xml
new file mode 100644
index 0000000..946d279
--- /dev/null
+++ b/res/drawable/carousel_item_card_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/color_surface" />
+    <corners android:radius="16dp" />
+</shape>
\ No newline at end of file
diff --git a/res/layout/clock_carousel.xml b/res/layout/clock_carousel.xml
index dbeb4dd..f6c408b 100644
--- a/res/layout/clock_carousel.xml
+++ b/res/layout/clock_carousel.xml
@@ -22,7 +22,7 @@
     android:layout_height="match_parent"
     app:layoutDescription="@xml/carousel_scene">
 
-    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+    <FrameLayout
         android:id="@+id/item_view_0"
         android:layout_width="@dimen/clock_carousel_item_width"
         android:layout_height="@dimen/clock_carousel_item_height"
@@ -30,14 +30,28 @@
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toStartOf="@+id/item_view_1"
         app:layout_constraintTop_toTopOf="parent">
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="center"
-            android:clipChildren="false" />
-    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
 
-    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+        <View
+            android:id="@+id/item_card_0"
+            android:layout_width="@dimen/clock_carousel_item_card_width"
+            android:layout_height="@dimen/clock_carousel_item_card_height"
+            android:layout_gravity="center"
+            android:background="@drawable/carousel_item_card_background"/>
+
+        <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+            android:id="@+id/clock_scale_view_0"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <FrameLayout
+                android:id="@+id/clock_host_view_0"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:clipChildren="false" />
+        </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+    </FrameLayout>
+
+    <FrameLayout
         android:id="@+id/item_view_1"
         android:layout_width="@dimen/clock_carousel_item_width"
         android:layout_height="@dimen/clock_carousel_item_height"
@@ -45,14 +59,28 @@
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toStartOf="@+id/item_view_2"
         app:layout_constraintTop_toTopOf="parent" >
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="center"
-            android:clipChildren="false"/>
-    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
 
-    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+        <View
+            android:id="@+id/item_card_1"
+            android:layout_width="@dimen/clock_carousel_item_card_width"
+            android:layout_height="@dimen/clock_carousel_item_card_height"
+            android:layout_gravity="center"
+            android:background="@drawable/carousel_item_card_background"/>
+
+        <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+            android:id="@+id/clock_scale_view_1"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <FrameLayout
+                android:id="@+id/clock_host_view_1"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:clipChildren="false"/>
+        </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+    </FrameLayout>
+
+    <FrameLayout
         android:id="@+id/item_view_2"
         android:layout_width="@dimen/clock_carousel_item_width"
         android:layout_height="@dimen/clock_carousel_item_height"
@@ -61,42 +89,84 @@
         app:layout_constraintHorizontal_bias="0.5"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent">
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="center"
-            android:clipChildren="false"/>
-    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
 
-    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+        <View
+            android:id="@+id/item_card_2"
+            android:layout_width="@dimen/clock_carousel_item_card_width"
+            android:layout_height="@dimen/clock_carousel_item_card_height"
+            android:layout_gravity="center"
+            android:background="@drawable/carousel_item_card_background"/>
+
+        <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+            android:id="@+id/clock_scale_view_2"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <FrameLayout
+                android:id="@+id/clock_host_view_2"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:clipChildren="false"/>
+        </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+    </FrameLayout>
+
+    <FrameLayout
         android:id="@+id/item_view_3"
         android:layout_width="@dimen/clock_carousel_item_width"
         android:layout_height="@dimen/clock_carousel_item_height"
         android:layout_marginStart="@dimen/clock_carousel_item_margin"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toEndOf="@+id/item_view_2"
-        app:layout_constraintTop_toTopOf="parent" >
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="center"
-            android:clipChildren="false"/>
-    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+        app:layout_constraintTop_toTopOf="parent">
 
-    <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+        <View
+            android:id="@+id/item_card_3"
+            android:layout_width="@dimen/clock_carousel_item_card_width"
+            android:layout_height="@dimen/clock_carousel_item_card_height"
+            android:layout_gravity="center"
+            android:background="@drawable/carousel_item_card_background"/>
+
+        <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+            android:id="@+id/clock_scale_view_3"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <FrameLayout
+                android:id="@+id/clock_host_view_3"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:clipChildren="false"/>
+        </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+    </FrameLayout>
+
+    <FrameLayout
         android:id="@+id/item_view_4"
         android:layout_width="@dimen/clock_carousel_item_width"
         android:layout_height="@dimen/clock_carousel_item_height"
         android:layout_marginStart="@dimen/clock_carousel_item_margin"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toEndOf="@+id/item_view_3"
-        app:layout_constraintTop_toTopOf="parent" >
-        <FrameLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <View
+            android:id="@+id/item_card_4"
+            android:layout_width="@dimen/clock_carousel_item_card_width"
+            android:layout_height="@dimen/clock_carousel_item_card_height"
             android:layout_gravity="center"
-            android:clipChildren="false" />
-    </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+            android:background="@drawable/carousel_item_card_background"/>
+
+        <com.android.wallpaper.picker.DisplayAspectRatioFrameLayout
+            android:id="@+id/clock_scale_view_4"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <FrameLayout
+                android:id="@+id/clock_host_view_4"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:clipChildren="false" />
+        </com.android.wallpaper.picker.DisplayAspectRatioFrameLayout>
+    </FrameLayout>
 
     <androidx.constraintlayout.helper.widget.Carousel
         android:id="@+id/carousel"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index cb4876a..9bcdd56 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -160,10 +160,8 @@
     <dimen name="clock_carousel_item_height">380dp</dimen>
     <dimen name="clock_carousel_item_margin">16dp</dimen>
     <dimen name="clock_carousel_guideline_margin">140dp</dimen>
-    <!-- Scale of the carousel items that are not selected and at the side -->
-    <dimen name="clock_carousel_scale" format="float">0.5</dimen>
-    <!-- Alpha of the carousel items that are not selected and at the side -->
-    <dimen name="clock_carousel_alpha" format="float">0.4</dimen>
+    <dimen name="clock_carousel_item_card_width">100dp</dimen>
+    <dimen name="clock_carousel_item_card_height">108dp</dimen>
 
     <!-- Clock color and size button -->
     <dimen name="clock_color_size_button_min_height">32dp</dimen>
diff --git a/res/xml/carousel_scene.xml b/res/xml/carousel_scene.xml
index e26ee14..267f0a1 100644
--- a/res/xml/carousel_scene.xml
+++ b/res/xml/carousel_scene.xml
@@ -42,12 +42,10 @@
             android:id="@+id/item_view_0"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintEnd_toStartOf="@id/guideline_start"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_1"
             android:layout_width="@dimen/clock_carousel_item_width"
@@ -58,13 +56,11 @@
             motion:layout_constraintEnd_toEndOf="parent"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_2"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintStart_toStartOf="@id/guideline_end"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -73,9 +69,6 @@
             android:id="@+id/item_view_3"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintStart_toEndOf="@+id/item_view_2"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -86,9 +79,6 @@
             android:id="@+id/item_view_0"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintEnd_toStartOf="@+id/item_view_1"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -97,12 +87,10 @@
             android:id="@+id/item_view_1"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintEnd_toStartOf="@id/guideline_start"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_2"
             android:layout_width="@dimen/clock_carousel_item_width"
@@ -113,13 +101,11 @@
             motion:layout_constraintEnd_toEndOf="parent"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_3"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintStart_toStartOf="@id/guideline_end"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -128,9 +114,6 @@
             android:id="@+id/item_view_4"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintStart_toEndOf="@+id/item_view_3"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -141,9 +124,6 @@
             android:id="@+id/item_view_1"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintEnd_toStartOf="@+id/item_view_2"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
@@ -152,12 +132,10 @@
             android:id="@+id/item_view_2"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintEnd_toStartOf="@id/guideline_start"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_3"
             android:layout_width="@dimen/clock_carousel_item_width"
@@ -168,16 +146,13 @@
             motion:layout_constraintEnd_toEndOf="parent"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
+
         <Constraint
             android:id="@+id/item_view_4"
             android:layout_width="@dimen/clock_carousel_item_width"
             android:layout_height="@dimen/clock_carousel_item_height"
-            android:scaleX="@dimen/clock_carousel_scale"
-            android:scaleY="@dimen/clock_carousel_scale"
-            android:alpha="@dimen/clock_carousel_alpha"
             motion:layout_constraintStart_toStartOf="@id/guideline_end"
             motion:layout_constraintTop_toTopOf="parent"
             motion:layout_constraintBottom_toBottomOf="parent" />
     </ConstraintSet>
-
 </MotionScene>
\ No newline at end of file
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 3eae7aa..48d3de3 100644
--- a/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
+++ b/src/com/android/customization/picker/clock/ui/view/ClockCarouselView.kt
@@ -17,15 +17,16 @@
 
 import android.content.Context
 import android.util.AttributeSet
+import android.util.Log
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.widget.FrameLayout
 import androidx.constraintlayout.helper.widget.Carousel
 import androidx.constraintlayout.motion.widget.MotionLayout
-import androidx.core.view.get
 import com.android.systemui.plugins.ClockController
 import com.android.wallpaper.R
+import java.lang.Float.max
 
 class ClockCarouselView(
     context: Context,
@@ -39,8 +40,12 @@
     private val carousel: Carousel
     private val motionLayout: MotionLayout
     private lateinit var adapter: ClockCarouselAdapter
-    private lateinit var scalingUpClock: ClockController
-    private lateinit var scalingDownClock: ClockController
+    private lateinit var scalingUpClockController: ClockController
+    private lateinit var scalingDownClockController: ClockController
+    private var scalingUpClockView: View? = null
+    private var scalingDownClockView: View? = null
+    private var showingCardView: View? = null
+    private var hidingCardView: View? = null
 
     init {
         val clockCarousel = LayoutInflater.from(context).inflate(R.layout.clock_carousel, this)
@@ -65,13 +70,25 @@
                     startId: Int,
                     endId: Int
                 ) {
+                    Log.d("mmpud", "onTransitionStarted")
                     val scalingDownClockId = adapter.clockIds[carousel.currentIndex]
                     val scalingUpIdx =
                         if (endId == R.id.next) (carousel.currentIndex + 1) % adapter.count()
                         else (carousel.currentIndex - 1 + adapter.count()) % adapter.count()
                     val scalingUpClockId = adapter.clockIds[scalingUpIdx]
-                    scalingDownClock = adapter.onGetClockController(scalingDownClockId)
-                    scalingUpClock = adapter.onGetClockController(scalingUpClockId)
+                    scalingDownClockController = adapter.onGetClockController(scalingDownClockId)
+                    scalingUpClockController = adapter.onGetClockController(scalingUpClockId)
+                    scalingDownClockView = motionLayout?.findViewById(R.id.clock_scale_view_2)
+                    scalingUpClockView =
+                        motionLayout?.findViewById(
+                            if (endId == R.id.next) R.id.clock_scale_view_3
+                            else R.id.clock_scale_view_1
+                        )
+                    showingCardView = motionLayout?.findViewById(R.id.item_card_2)
+                    hidingCardView =
+                        motionLayout?.findViewById(
+                            if (endId == R.id.next) R.id.item_card_3 else R.id.item_card_1
+                        )
                 }
 
                 override fun onTransitionChange(
@@ -80,11 +97,22 @@
                     endId: Int,
                     progress: Float
                 ) {
-                    scalingDownClock.animations.onPickerCarouselSwiping(
+                    scalingDownClockController.animations.onPickerCarouselSwiping(
                         1 - progress,
                         getPreviewRatio()
                     )
-                    scalingUpClock.animations.onPickerCarouselSwiping(progress, getPreviewRatio())
+                    scalingUpClockController.animations.onPickerCarouselSwiping(
+                        progress,
+                        getPreviewRatio()
+                    )
+                    val scalingUpScale = getScalingUpScale(progress)
+                    val scalingDownScale = getScalingDownScale(progress)
+                    scalingUpClockView?.scaleX = scalingUpScale
+                    scalingUpClockView?.scaleY = scalingUpScale
+                    scalingDownClockView?.scaleX = scalingDownScale
+                    scalingDownClockView?.scaleY = scalingDownScale
+                    showingCardView?.alpha = getShowingAlpha(progress)
+                    hidingCardView?.alpha = getHidingAlpha(progress)
                 }
 
                 override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {}
@@ -117,8 +145,17 @@
         }
 
         override fun populate(view: View?, index: Int) {
-            val viewRoot = view as ViewGroup
-            val clockHostView = viewRoot[0] as ViewGroup
+            val viewRoot = view as? ViewGroup ?: return
+            val cardView =
+                getClockCardViewId(viewRoot.id)?.let { viewRoot.findViewById(it) as? View }
+                    ?: return
+            val clockScaleView =
+                getClockScaleViewId(viewRoot.id)?.let { viewRoot.findViewById(it) as? View }
+                    ?: return
+            val clockHostView =
+                getClockHostViewId(viewRoot.id)?.let { viewRoot.findViewById(it) as? ViewGroup }
+                    ?: return
+
             clockHostView.removeAllViews()
             val clockView = onGetClockController(clockIds[index]).largeClock.view
             // The clock view might still be attached to an existing parent. Detach before adding to
@@ -126,11 +163,17 @@
             (clockView.parent as? ViewGroup)?.removeView(clockView)
             clockHostView.addView(clockView)
             // initialize scaling state for all clocks
-            if (view.id != MIDDLE_VIEW_IN_START_STATE) {
+            if (!isMiddleView(viewRoot.id)) {
+                cardView.alpha = 1f
+                clockScaleView.scaleX = CLOCK_CAROUSEL_VIEW_SCALE
+                clockScaleView.scaleY = CLOCK_CAROUSEL_VIEW_SCALE
                 onGetClockController(clockIds[index])
                     .animations
                     .onPickerCarouselSwiping(0F, getPreviewRatio())
             } else {
+                cardView.alpha = 0f
+                clockScaleView.scaleX = 1f
+                clockScaleView.scaleY = 1f
                 onGetClockController(clockIds[index])
                     .animations
                     .onPickerCarouselSwiping(1F, getPreviewRatio())
@@ -143,6 +186,56 @@
     }
 
     companion object {
-        const val MIDDLE_VIEW_IN_START_STATE = R.id.item_view_2
+        const val CLOCK_CAROUSEL_VIEW_SCALE = 0.5f
+
+        fun getScalingUpScale(progress: Float) =
+            CLOCK_CAROUSEL_VIEW_SCALE + progress * (1f - CLOCK_CAROUSEL_VIEW_SCALE)
+
+        fun getScalingDownScale(progress: Float) = 1f - progress * (1f - CLOCK_CAROUSEL_VIEW_SCALE)
+
+        // This makes the card only starts to reveal in the last quarter of the trip so
+        // the card won't overlap the preview.
+        fun getShowingAlpha(progress: Float) = max(progress - 0.75f, 0f) * 4
+
+        // This makes the card starts to hide in the first quarter of the trip so the
+        // card won't overlap the preview.
+        fun getHidingAlpha(progress: Float) = max(1f - progress * 4, 0f)
+
+        fun getClockHostViewId(rootViewId: Int): Int? {
+            return when (rootViewId) {
+                R.id.item_view_0 -> R.id.clock_host_view_0
+                R.id.item_view_1 -> R.id.clock_host_view_1
+                R.id.item_view_2 -> R.id.clock_host_view_2
+                R.id.item_view_3 -> R.id.clock_host_view_3
+                R.id.item_view_4 -> R.id.clock_host_view_4
+                else -> null
+            }
+        }
+
+        fun getClockScaleViewId(rootViewId: Int): Int? {
+            return when (rootViewId) {
+                R.id.item_view_0 -> R.id.clock_scale_view_0
+                R.id.item_view_1 -> R.id.clock_scale_view_1
+                R.id.item_view_2 -> R.id.clock_scale_view_2
+                R.id.item_view_3 -> R.id.clock_scale_view_3
+                R.id.item_view_4 -> R.id.clock_scale_view_4
+                else -> null
+            }
+        }
+
+        fun getClockCardViewId(rootViewId: Int): Int? {
+            return when (rootViewId) {
+                R.id.item_view_0 -> R.id.item_card_0
+                R.id.item_view_1 -> R.id.item_card_1
+                R.id.item_view_2 -> R.id.item_card_2
+                R.id.item_view_3 -> R.id.item_card_3
+                R.id.item_view_4 -> R.id.item_card_4
+                else -> null
+            }
+        }
+
+        fun isMiddleView(rootViewId: Int): Boolean {
+            return rootViewId == R.id.item_view_2
+        }
     }
 }