Loading packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ClockTransition.kt +2 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.ui.composable.blueprint import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.tween import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.SceneKey Loading @@ -39,7 +40,7 @@ object ClockTransition { transitioningToSmallClock() } from(ClockScenes.splitShadeLargeClockScene, to = ClockScenes.largeClockScene) { spec = tween(1000) spec = tween(1000, easing = LinearEasing) } } Loading packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt +38 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.ui.composable.section import android.content.res.Resources import android.view.View import android.view.ViewGroup import android.widget.FrameLayout Loading @@ -23,6 +24,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier Loading @@ -36,6 +38,8 @@ import com.android.systemui.customization.R as customizationR import com.android.systemui.customization.R import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.largeClockElementKey import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.smallClockElementKey import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.largeClockScene import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.splitShadeLargeClockScene import com.android.systemui.keyguard.ui.composable.modifier.burnInAware import com.android.systemui.keyguard.ui.composable.modifier.onTopPlacementChanged import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel Loading Loading @@ -95,6 +99,36 @@ constructor( if (currentClock?.largeClock?.view == null) { return } // Centering animation for clocks that have custom position animations. LaunchedEffect(layoutState.currentTransition?.progress) { val transition = layoutState.currentTransition ?: return@LaunchedEffect if (currentClock?.largeClock?.config?.hasCustomPositionUpdatedAnimation != true) { return@LaunchedEffect } // If we are not doing the centering animation, do not animate. val progress = if (transition.isTransitioningBetween(largeClockScene, splitShadeLargeClockScene)) { transition.progress } else { 1f } val distance = if (transition.toScene == splitShadeLargeClockScene) { -getClockCenteringDistance() } else { getClockCenteringDistance() } .toFloat() val largeClock = checkNotNull(currentClock).largeClock largeClock.animations.onPositionUpdated( distance = distance, fraction = progress, ) } MovableElement(key = largeClockElementKey, modifier = modifier) { content { AndroidView( Loading @@ -120,4 +154,8 @@ constructor( (clockView.parent as? ViewGroup)?.removeView(clockView) addView(clockView) } fun getClockCenteringDistance(): Float { return Resources.getSystem().displayMetrics.widthPixels / 4f } } packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt +46 −17 Original line number Diff line number Diff line Loading @@ -16,12 +16,16 @@ package com.android.systemui.keyguard.ui.composable.section import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState Loading @@ -31,11 +35,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.SceneTransitionLayout import com.android.compose.modifiers.thenIf import com.android.systemui.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.largeClockScene import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.smallClockScene import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.splitShadeLargeClockScene Loading Loading @@ -63,6 +68,9 @@ constructor( ) { val isLargeClockVisible by clockViewModel.isLargeClockVisible.collectAsState() val currentClockLayout by clockViewModel.currentClockLayout.collectAsState() val hasCustomPositionUpdatedAnimation by clockViewModel.hasCustomPositionUpdatedAnimation.collectAsState() val currentScene = when (currentClockLayout) { KeyguardClockViewModel.ClockLayout.SPLIT_SHADE_LARGE_CLOCK -> Loading Loading @@ -94,12 +102,10 @@ constructor( transitions = ClockTransition.defaultClockTransitions, enableInterruptions = false, ) { scene(ClockScenes.splitShadeLargeClockScene) { Row( modifier = Modifier.fillMaxSize(), ) { scene(splitShadeLargeClockScene) { Box(modifier = Modifier.fillMaxSize()) { Column( modifier = Modifier.fillMaxHeight().weight(weight = 1f), modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, ) { with(smartSpaceSection) { Loading @@ -108,8 +114,34 @@ constructor( onTopChanged = burnIn.onSmartspaceTopChanged, ) } with(clockSection) { LargeClock(modifier = Modifier.fillMaxWidth()) } with(clockSection) { LargeClock( modifier = Modifier.fillMaxSize().thenIf( !hasCustomPositionUpdatedAnimation ) { // If we do not have a custom position animation, we want // the clock to be on one half of the screen. Modifier.offset { IntOffset( x = -clockSection .getClockCenteringDistance() .toInt(), y = 0, ) } } ) } } } Row( modifier = Modifier.fillMaxSize(), ) { Spacer(modifier = Modifier.weight(weight = 1f)) with(notificationSection) { Notifications( modifier = Loading @@ -121,7 +153,7 @@ constructor( } } scene(ClockScenes.splitShadeSmallClockScene) { scene(splitShadeSmallClockScene) { Row( modifier = Modifier.fillMaxSize(), ) { Loading @@ -133,7 +165,7 @@ constructor( SmallClock( burnInParams = burnIn.parameters, onTopChanged = burnIn.onSmallClockTopChanged, modifier = Modifier.fillMaxWidth() modifier = Modifier.wrapContentSize() ) } with(smartSpaceSection) { Loading @@ -155,13 +187,13 @@ constructor( } } scene(ClockScenes.smallClockScene) { scene(smallClockScene) { Column { with(clockSection) { SmallClock( burnInParams = burnIn.parameters, onTopChanged = burnIn.onSmallClockTopChanged, modifier = Modifier.fillMaxWidth() modifier = Modifier.wrapContentSize() ) } with(smartSpaceSection) { Loading @@ -172,15 +204,12 @@ constructor( } with(mediaCarouselSection) { MediaCarousel() } with(notificationSection) { Notifications( modifier = androidx.compose.ui.Modifier.fillMaxWidth().weight(weight = 1f) ) Notifications(modifier = Modifier.fillMaxWidth().weight(weight = 1f)) } } } scene(ClockScenes.largeClockScene) { scene(largeClockScene) { Column { with(smartSpaceSection) { SmartSpace( Loading @@ -188,7 +217,7 @@ constructor( onTopChanged = burnIn.onSmartspaceTopChanged, ) } with(clockSection) { LargeClock(modifier = Modifier.fillMaxWidth()) } with(clockSection) { LargeClock(modifier = Modifier.fillMaxSize()) } } } } Loading packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt +56 −17 Original line number Diff line number Diff line Loading @@ -517,29 +517,68 @@ class AnimatableClockView @JvmOverloads constructor( val currentMoveAmount = left - clockStartLeft val digitOffsetDirection = if (isLayoutRtl) -1 else 1 for (i in 0 until NUM_DIGITS) { val digitFraction = getDigitFraction( digit = i, isMovingToCenter = isMovingToCenter, fraction = moveFraction, ) val moveAmountForDigit = currentMoveAmount * digitFraction val moveAmountDeltaForDigit = moveAmountForDigit - currentMoveAmount glyphOffsets[i] = digitOffsetDirection * moveAmountDeltaForDigit } invalidate() } /** * Offsets the glyphs of the clock for the step clock animation. * * The animation makes the glyphs of the clock move at different speeds, when the clock is * moving horizontally. This method uses direction, distance, and fraction to determine offset. * * @param distance is the total distance in pixels to offset the glyphs when animation * completes. Negative distance means we are animating the position towards the center. * @param fraction fraction of the clock movement. 0 means it is at the beginning, and 1 * means it finished moving. */ fun offsetGlyphsForStepClockAnimation( distance: Float, fraction: Float, ) { for (i in 0 until NUM_DIGITS) { val dir = if (isLayoutRtl) -1 else 1 val digitFraction = getDigitFraction(digit = i, isMovingToCenter = distance > 0, fraction = fraction) val moveAmountForDigit = dir * distance * digitFraction glyphOffsets[i] = moveAmountForDigit if (distance > 0) { // If distance > 0 then we are moving from the left towards the center. // We need ensure that the glyphs are offset to the initial position. glyphOffsets -= dir * distance } } invalidate() } private fun getDigitFraction(digit: Int, isMovingToCenter: Boolean, fraction: Float): Float { // The delay for the digit, in terms of fraction (i.e. the digit should not move // during 0.0 - 0.1). val digitInitialDelay = if (isMovingToCenter) { moveToCenterDelays[i] * MOVE_DIGIT_STEP moveToCenterDelays[digit] * MOVE_DIGIT_STEP } else { moveToSideDelays[i] * MOVE_DIGIT_STEP moveToSideDelays[digit] * MOVE_DIGIT_STEP } val digitFraction = MOVE_INTERPOLATOR.getInterpolation( return MOVE_INTERPOLATOR.getInterpolation( constrainedMap( 0.0f, 1.0f, digitInitialDelay, digitInitialDelay + AVAILABLE_ANIMATION_TIME, moveFraction fraction, ) ) val moveAmountForDigit = currentMoveAmount * digitFraction val moveAmountDeltaForDigit = moveAmountForDigit - currentMoveAmount glyphOffsets[i] = digitOffsetDirection * moveAmountDeltaForDigit } invalidate() } // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often. Loading packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt +10 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,10 @@ class DefaultClockController( fun offsetGlyphsForStepClockAnimation(fromLeft: Int, direction: Int, fraction: Float) { view.offsetGlyphsForStepClockAnimation(fromLeft, direction, fraction) } fun offsetGlyphsForStepClockAnimation(distance: Float, fraction: Float) { view.offsetGlyphsForStepClockAnimation(distance, fraction) } } inner class DefaultClockEvents : ClockEvents { Loading Loading @@ -316,6 +320,8 @@ class DefaultClockController( } override fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) {} override fun onPositionUpdated(distance: Float, fraction: Float) {} } inner class LargeClockAnimations( Loading @@ -326,6 +332,10 @@ class DefaultClockController( override fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) { largeClock.offsetGlyphsForStepClockAnimation(fromLeft, direction, fraction) } override fun onPositionUpdated(distance: Float, fraction: Float) { largeClock.offsetGlyphsForStepClockAnimation(distance, fraction) } } class AnimationState( Loading Loading
packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ClockTransition.kt +2 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.ui.composable.blueprint import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.tween import com.android.compose.animation.scene.ElementKey import com.android.compose.animation.scene.SceneKey Loading @@ -39,7 +40,7 @@ object ClockTransition { transitioningToSmallClock() } from(ClockScenes.splitShadeLargeClockScene, to = ClockScenes.largeClockScene) { spec = tween(1000) spec = tween(1000, easing = LinearEasing) } } Loading
packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/DefaultClockSection.kt +38 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.keyguard.ui.composable.section import android.content.res.Resources import android.view.View import android.view.ViewGroup import android.widget.FrameLayout Loading @@ -23,6 +24,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier Loading @@ -36,6 +38,8 @@ import com.android.systemui.customization.R as customizationR import com.android.systemui.customization.R import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.largeClockElementKey import com.android.systemui.keyguard.ui.composable.blueprint.ClockElementKeys.smallClockElementKey import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.largeClockScene import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.splitShadeLargeClockScene import com.android.systemui.keyguard.ui.composable.modifier.burnInAware import com.android.systemui.keyguard.ui.composable.modifier.onTopPlacementChanged import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel Loading Loading @@ -95,6 +99,36 @@ constructor( if (currentClock?.largeClock?.view == null) { return } // Centering animation for clocks that have custom position animations. LaunchedEffect(layoutState.currentTransition?.progress) { val transition = layoutState.currentTransition ?: return@LaunchedEffect if (currentClock?.largeClock?.config?.hasCustomPositionUpdatedAnimation != true) { return@LaunchedEffect } // If we are not doing the centering animation, do not animate. val progress = if (transition.isTransitioningBetween(largeClockScene, splitShadeLargeClockScene)) { transition.progress } else { 1f } val distance = if (transition.toScene == splitShadeLargeClockScene) { -getClockCenteringDistance() } else { getClockCenteringDistance() } .toFloat() val largeClock = checkNotNull(currentClock).largeClock largeClock.animations.onPositionUpdated( distance = distance, fraction = progress, ) } MovableElement(key = largeClockElementKey, modifier = modifier) { content { AndroidView( Loading @@ -120,4 +154,8 @@ constructor( (clockView.parent as? ViewGroup)?.removeView(clockView) addView(clockView) } fun getClockCenteringDistance(): Float { return Resources.getSystem().displayMetrics.widthPixels / 4f } }
packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/TopAreaSection.kt +46 −17 Original line number Diff line number Diff line Loading @@ -16,12 +16,16 @@ package com.android.systemui.keyguard.ui.composable.section import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState Loading @@ -31,11 +35,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import com.android.compose.animation.scene.SceneTransitionLayout import com.android.compose.modifiers.thenIf import com.android.systemui.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.largeClockScene import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.smallClockScene import com.android.systemui.keyguard.ui.composable.blueprint.ClockScenes.splitShadeLargeClockScene Loading Loading @@ -63,6 +68,9 @@ constructor( ) { val isLargeClockVisible by clockViewModel.isLargeClockVisible.collectAsState() val currentClockLayout by clockViewModel.currentClockLayout.collectAsState() val hasCustomPositionUpdatedAnimation by clockViewModel.hasCustomPositionUpdatedAnimation.collectAsState() val currentScene = when (currentClockLayout) { KeyguardClockViewModel.ClockLayout.SPLIT_SHADE_LARGE_CLOCK -> Loading Loading @@ -94,12 +102,10 @@ constructor( transitions = ClockTransition.defaultClockTransitions, enableInterruptions = false, ) { scene(ClockScenes.splitShadeLargeClockScene) { Row( modifier = Modifier.fillMaxSize(), ) { scene(splitShadeLargeClockScene) { Box(modifier = Modifier.fillMaxSize()) { Column( modifier = Modifier.fillMaxHeight().weight(weight = 1f), modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, ) { with(smartSpaceSection) { Loading @@ -108,8 +114,34 @@ constructor( onTopChanged = burnIn.onSmartspaceTopChanged, ) } with(clockSection) { LargeClock(modifier = Modifier.fillMaxWidth()) } with(clockSection) { LargeClock( modifier = Modifier.fillMaxSize().thenIf( !hasCustomPositionUpdatedAnimation ) { // If we do not have a custom position animation, we want // the clock to be on one half of the screen. Modifier.offset { IntOffset( x = -clockSection .getClockCenteringDistance() .toInt(), y = 0, ) } } ) } } } Row( modifier = Modifier.fillMaxSize(), ) { Spacer(modifier = Modifier.weight(weight = 1f)) with(notificationSection) { Notifications( modifier = Loading @@ -121,7 +153,7 @@ constructor( } } scene(ClockScenes.splitShadeSmallClockScene) { scene(splitShadeSmallClockScene) { Row( modifier = Modifier.fillMaxSize(), ) { Loading @@ -133,7 +165,7 @@ constructor( SmallClock( burnInParams = burnIn.parameters, onTopChanged = burnIn.onSmallClockTopChanged, modifier = Modifier.fillMaxWidth() modifier = Modifier.wrapContentSize() ) } with(smartSpaceSection) { Loading @@ -155,13 +187,13 @@ constructor( } } scene(ClockScenes.smallClockScene) { scene(smallClockScene) { Column { with(clockSection) { SmallClock( burnInParams = burnIn.parameters, onTopChanged = burnIn.onSmallClockTopChanged, modifier = Modifier.fillMaxWidth() modifier = Modifier.wrapContentSize() ) } with(smartSpaceSection) { Loading @@ -172,15 +204,12 @@ constructor( } with(mediaCarouselSection) { MediaCarousel() } with(notificationSection) { Notifications( modifier = androidx.compose.ui.Modifier.fillMaxWidth().weight(weight = 1f) ) Notifications(modifier = Modifier.fillMaxWidth().weight(weight = 1f)) } } } scene(ClockScenes.largeClockScene) { scene(largeClockScene) { Column { with(smartSpaceSection) { SmartSpace( Loading @@ -188,7 +217,7 @@ constructor( onTopChanged = burnIn.onSmartspaceTopChanged, ) } with(clockSection) { LargeClock(modifier = Modifier.fillMaxWidth()) } with(clockSection) { LargeClock(modifier = Modifier.fillMaxSize()) } } } } Loading
packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt +56 −17 Original line number Diff line number Diff line Loading @@ -517,29 +517,68 @@ class AnimatableClockView @JvmOverloads constructor( val currentMoveAmount = left - clockStartLeft val digitOffsetDirection = if (isLayoutRtl) -1 else 1 for (i in 0 until NUM_DIGITS) { val digitFraction = getDigitFraction( digit = i, isMovingToCenter = isMovingToCenter, fraction = moveFraction, ) val moveAmountForDigit = currentMoveAmount * digitFraction val moveAmountDeltaForDigit = moveAmountForDigit - currentMoveAmount glyphOffsets[i] = digitOffsetDirection * moveAmountDeltaForDigit } invalidate() } /** * Offsets the glyphs of the clock for the step clock animation. * * The animation makes the glyphs of the clock move at different speeds, when the clock is * moving horizontally. This method uses direction, distance, and fraction to determine offset. * * @param distance is the total distance in pixels to offset the glyphs when animation * completes. Negative distance means we are animating the position towards the center. * @param fraction fraction of the clock movement. 0 means it is at the beginning, and 1 * means it finished moving. */ fun offsetGlyphsForStepClockAnimation( distance: Float, fraction: Float, ) { for (i in 0 until NUM_DIGITS) { val dir = if (isLayoutRtl) -1 else 1 val digitFraction = getDigitFraction(digit = i, isMovingToCenter = distance > 0, fraction = fraction) val moveAmountForDigit = dir * distance * digitFraction glyphOffsets[i] = moveAmountForDigit if (distance > 0) { // If distance > 0 then we are moving from the left towards the center. // We need ensure that the glyphs are offset to the initial position. glyphOffsets -= dir * distance } } invalidate() } private fun getDigitFraction(digit: Int, isMovingToCenter: Boolean, fraction: Float): Float { // The delay for the digit, in terms of fraction (i.e. the digit should not move // during 0.0 - 0.1). val digitInitialDelay = if (isMovingToCenter) { moveToCenterDelays[i] * MOVE_DIGIT_STEP moveToCenterDelays[digit] * MOVE_DIGIT_STEP } else { moveToSideDelays[i] * MOVE_DIGIT_STEP moveToSideDelays[digit] * MOVE_DIGIT_STEP } val digitFraction = MOVE_INTERPOLATOR.getInterpolation( return MOVE_INTERPOLATOR.getInterpolation( constrainedMap( 0.0f, 1.0f, digitInitialDelay, digitInitialDelay + AVAILABLE_ANIMATION_TIME, moveFraction fraction, ) ) val moveAmountForDigit = currentMoveAmount * digitFraction val moveAmountDeltaForDigit = moveAmountForDigit - currentMoveAmount glyphOffsets[i] = digitOffsetDirection * moveAmountDeltaForDigit } invalidate() } // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often. Loading
packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt +10 −0 Original line number Diff line number Diff line Loading @@ -232,6 +232,10 @@ class DefaultClockController( fun offsetGlyphsForStepClockAnimation(fromLeft: Int, direction: Int, fraction: Float) { view.offsetGlyphsForStepClockAnimation(fromLeft, direction, fraction) } fun offsetGlyphsForStepClockAnimation(distance: Float, fraction: Float) { view.offsetGlyphsForStepClockAnimation(distance, fraction) } } inner class DefaultClockEvents : ClockEvents { Loading Loading @@ -316,6 +320,8 @@ class DefaultClockController( } override fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) {} override fun onPositionUpdated(distance: Float, fraction: Float) {} } inner class LargeClockAnimations( Loading @@ -326,6 +332,10 @@ class DefaultClockController( override fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) { largeClock.offsetGlyphsForStepClockAnimation(fromLeft, direction, fraction) } override fun onPositionUpdated(distance: Float, fraction: Float) { largeClock.offsetGlyphsForStepClockAnimation(distance, fraction) } } class AnimationState( Loading