diff options
| author | 2025-01-29 15:52:35 +0000 | |
|---|---|---|
| committer | 2025-01-31 17:58:19 +0000 | |
| commit | 552c1df23e8a38d4226695d6cfaa659b783008e7 (patch) | |
| tree | 8f63ab9990d8060c5d95a31f3267f99ff7390472 | |
| parent | c896855ced8b89c829b11b184b1568ad08bb3228 (diff) | |
Translate digits on AOD to not be quite so wide
This uses two views stacked vertically instead of 4 individual views.
Doing this improves behavior for moving from very wide axes to relative
thin ones on AOD, and provides much better spacing.
I'm hopeful this will also improve our memory usage as it effectively
halves the number of text animators and views we're allocating in
using. We'll see about this when the metrics come in. If it is
significant, I'll probably move to one view with all four digits, but
that layout proved tricker to implement than this for the time being.
Finally, this also breaks the stepping animation. That'll need to be
addressed, but the implementation of that will depend on where we
land for number of child views we're using here. b/393577936
tracks that follow up work.
Bug: 391858439
Bug: 385338722
Test: Manually checked spacing
Flag: com.android.systemui.shared.clock_reactive_variants
Change-Id: Ib6f67763e77a3ceeeea4a5cbf97dcad6307867fe
6 files changed, 72 insertions, 65 deletions
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt index 9fb60c75b046..d5966554d1a4 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ComposedDigitalLayerController.kt @@ -55,31 +55,20 @@ class ComposedDigitalLayerController(private val clockCtx: ClockContext) :          val layerCfg =              LayerConfig(                  style = FontTextStyle(lineHeight = 147.25f), +                timespec = DigitalTimespec.DIGIT_PAIR, +                alignment = DigitalAlignment(HorizontalAlignment.CENTER, VerticalAlignment.CENTER),                  aodStyle =                      FontTextStyle(                          transitionInterpolator = Interpolators.EMPHASIZED,                          transitionDuration = 750,                      ), -                alignment = -                    DigitalAlignment(HorizontalAlignment.CENTER, VerticalAlignment.BASELINE), -                // Placeholders -                timespec = DigitalTimespec.TIME_FULL_FORMAT, +                // Placeholder                  dateTimeFormat = "hh:mm",              ) -        createController( -            layerCfg.copy(timespec = DigitalTimespec.FIRST_DIGIT, dateTimeFormat = "hh") -        ) -        createController( -            layerCfg.copy(timespec = DigitalTimespec.SECOND_DIGIT, dateTimeFormat = "hh") -        ) -        createController( -            layerCfg.copy(timespec = DigitalTimespec.FIRST_DIGIT, dateTimeFormat = "mm") -        ) -        createController( -            layerCfg.copy(timespec = DigitalTimespec.SECOND_DIGIT, dateTimeFormat = "mm") -        ) +        createController(layerCfg.copy(dateTimeFormat = "hh")) +        createController(layerCfg.copy(dateTimeFormat = "mm"))      }      private fun refreshTime() { diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt index e2bbe0fef3c0..70815ad2b865 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/FlexClockFaceController.kt @@ -147,21 +147,6 @@ class FlexClockFaceController(clockCtx: ClockContext, private val isLargeClock:           * keyguard_large_clock_top_margin from default clock           */          override fun onTargetRegionChanged(targetRegion: Rect?) { -            // When a clock needs to be aligned with screen, like weather clock -            // it needs to offset back the translation of keyguard_large_clock_top_margin -            if (isLargeClock && (view as FlexClockView).isAlignedWithScreen()) { -                val topMargin = keyguardLargeClockTopMargin -                targetRegion?.let { -                    val (_, yDiff) = computeLayoutDiff(view, it, isLargeClock) -                    // In LS, we use yDiff to counter translate -                    // the translation of KeyguardLargeClockTopMargin -                    // With the targetRegion passed from picker, -                    // we will have yDiff = 0, no translation is needed for weather clock -                    if (yDiff.toInt() != 0) view.translationY = yDiff - topMargin / 2 -                } -                return -            } -              var maxWidth = 0f              var maxHeight = 0f @@ -230,7 +215,7 @@ class FlexClockFaceController(clockCtx: ClockContext, private val isLargeClock:              }              override fun onPickerCarouselSwiping(swipingFraction: Float) { -                if (isLargeClock && !(view as FlexClockView).isAlignedWithScreen()) { +                if (isLargeClock) {                      view.translationY = keyguardLargeClockTopMargin / 2F * swipingFraction                  }                  layerController.animations.onPickerCarouselSwiping(swipingFraction) @@ -250,6 +235,7 @@ class FlexClockFaceController(clockCtx: ClockContext, private val isLargeClock:      companion object {          val SMALL_CLOCK_MAX_WDTH = 120f +          val SMALL_LAYER_CONFIG =              LayerConfig(                  timespec = DigitalTimespec.TIME_FULL_FORMAT, diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt index 82fc35012dbc..ccb0b8200d32 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/SimpleDigitalHandLayerController.kt @@ -71,6 +71,7 @@ data class FontTextStyle(  enum class DigitalTimespec {      TIME_FULL_FORMAT, +    DIGIT_PAIR,      FIRST_DIGIT,      SECOND_DIGIT,  } @@ -120,6 +121,28 @@ open class SimpleDigitalHandLayerController(          }      } +    private fun applyLayout() { +        // TODO: Remove NO-OP +        if (view.layoutParams is RelativeLayout.LayoutParams) { +            val lp = view.layoutParams as RelativeLayout.LayoutParams +            lp.addRule(RelativeLayout.TEXT_ALIGNMENT_CENTER) +            when (view.id) { +                R.id.HOUR_DIGIT_PAIR -> { +                    lp.addRule(RelativeLayout.CENTER_VERTICAL) +                    lp.addRule(RelativeLayout.ALIGN_PARENT_START) +                } +                R.id.MINUTE_DIGIT_PAIR -> { +                    lp.addRule(RelativeLayout.CENTER_VERTICAL) +                    lp.addRule(RelativeLayout.END_OF, R.id.HOUR_DIGIT_PAIR) +                } +                else -> { +                    throw Exception("cannot apply two pairs layout to view ${view.id}") +                } +            } +            view.layoutParams = lp +        } +    } +      override val events =          object : ClockEvents {              override var isReactiveTouchInteractionEnabled = false @@ -154,6 +177,7 @@ open class SimpleDigitalHandLayerController(      override val animations =          object : ClockAnimations {              override fun enter() { +                applyLayout()                  refreshTime()              } @@ -169,6 +193,7 @@ open class SimpleDigitalHandLayerController(              }              override fun fold(fraction: Float) { +                applyLayout()                  refreshTime()              } diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/TimespecHandler.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/TimespecHandler.kt index 37db783aba53..8b3b92921ee0 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/TimespecHandler.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/TimespecHandler.kt @@ -106,19 +106,16 @@ class DigitalTimespecHandler(          )      } -    private fun getSingleDigit(): String { -        val isFirstDigit = timespec == DigitalTimespec.FIRST_DIGIT +    private fun getSingleDigit(offset: Int): String {          val text = dateFormat.format(cal.time).toString() -        return text.substring( -            if (isFirstDigit) 0 else text.length - 1, -            if (isFirstDigit) text.length - 1 else text.length, -        ) +        return text.substring(offset, offset + 1)      }      fun getDigitString(): String {          return when (timespec) { -            DigitalTimespec.FIRST_DIGIT, -            DigitalTimespec.SECOND_DIGIT -> getSingleDigit() +            DigitalTimespec.FIRST_DIGIT -> getSingleDigit(0) +            DigitalTimespec.SECOND_DIGIT -> getSingleDigit(1) +            DigitalTimespec.DIGIT_PAIR -> dateFormat.format(cal.time).toString()              DigitalTimespec.TIME_FULL_FORMAT -> dateFormat.format(cal.time).toString()          }      } diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt index 55750b5e0925..f0f344a605a9 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/FlexClockView.kt @@ -87,7 +87,7 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {      protected fun calculateSize(widthMeasureSpec: Int, heightMeasureSpec: Int): Point? {          maxSingleDigitSize = Point(-1, -1) -        val bottomLocation: (textView: SimpleDigitalClockTextView) -> Int = { textView -> +        val viewHeight: (textView: SimpleDigitalClockTextView) -> Int = { textView ->              if (isMonoVerticalNumericLineSpacing) {                  maxSingleDigitSize.y              } else { @@ -98,9 +98,15 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {          digitalClockTextViewMap.forEach { (_, textView) ->              textView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED)              maxSingleDigitSize.x = max(maxSingleDigitSize.x, textView.measuredWidth) -            maxSingleDigitSize.y = max(bottomLocation(textView), textView.measuredHeight) +            maxSingleDigitSize.y = max(viewHeight(textView), textView.measuredHeight)          }          aodTranslate = Point(0, 0) +        // TODO(b/364680879): Cleanup +        /* +        aodTranslate = Point( +            (maxSingleDigitSize.x * AOD_HORIZONTAL_TRANSLATE_RATIO).toInt(), +            (maxSingleDigitSize.y * AOD_VERTICAL_TRANSLATE_RATIO).toInt()) +        */          return Point(              ((maxSingleDigitSize.x + abs(aodTranslate.x)) * 2),              ((maxSingleDigitSize.y + abs(aodTranslate.y)) * 2), @@ -112,6 +118,10 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {          digitLeftTopMap[R.id.HOUR_SECOND_DIGIT] = Point(maxSingleDigitSize.x, 0)          digitLeftTopMap[R.id.MINUTE_FIRST_DIGIT] = Point(0, maxSingleDigitSize.y)          digitLeftTopMap[R.id.MINUTE_SECOND_DIGIT] = Point(maxSingleDigitSize) +        digitLeftTopMap[R.id.HOUR_DIGIT_PAIR] = Point(maxSingleDigitSize.x / 2, 0) +        // Add a small vertical buffer for the second digit pair +        digitLeftTopMap[R.id.MINUTE_DIGIT_PAIR] = +            Point(maxSingleDigitSize.x / 2, (maxSingleDigitSize.y * 1.05f).toInt())          digitLeftTopMap.forEach { (_, point) ->              point.x += abs(aodTranslate.x)              point.y += abs(aodTranslate.y) @@ -179,9 +189,9 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {              // save canvas location in anticipation of restoration later              canvas.save()              val xTranslateAmount = -                digitOffsets.getOrDefault(id, 0f) + digitLeftTopMap[id]!!.x.toFloat() +                digitOffsets.getOrDefault(id, 0f) + (digitLeftTopMap[id]?.x?.toFloat() ?: 0f)              // move canvas to location that the textView would like -            canvas.translate(xTranslateAmount, digitLeftTopMap[id]!!.y.toFloat()) +            canvas.translate(xTranslateAmount, digitLeftTopMap[id]?.y?.toFloat() ?: 0f)              // draw the textView at the location of the canvas above              textView.draw(canvas)              // reset the canvas location back to 0 without drawing @@ -189,8 +199,6 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {          }      } -    fun isAlignedWithScreen(): Boolean = false -      fun onLocaleChanged(locale: Locale) {          updateLocale(locale)          requestLayout() @@ -302,23 +310,17 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {          clockMoveDirection: Int,          moveFraction: Float,      ) { +        // TODO(b/393577936): The step animation isn't correct with the two pairs approach          val isMovingToCenter = if (isLayoutRtl) clockMoveDirection < 0 else clockMoveDirection > 0          // The sign of moveAmountDeltaForDigit is already set here          // we can interpret (left - clockStartLeft) as (destinationPosition - originPosition)          // so we no longer need to multiply direct sign to moveAmountDeltaForDigit          val currentMoveAmount = left - clockStartLeft -        for (i in 0 until NUM_DIGITS) { -            val mapIndexToId = -                when (i) { -                    0 -> R.id.HOUR_FIRST_DIGIT -                    1 -> R.id.HOUR_SECOND_DIGIT -                    2 -> R.id.MINUTE_FIRST_DIGIT -                    3 -> R.id.MINUTE_SECOND_DIGIT -                    else -> -1 -                } +        var index = 0 +        digitalClockTextViewMap.forEach { id, _ ->              val digitFraction =                  getDigitFraction( -                    digit = i, +                    digit = index++,                      isMovingToCenter = isMovingToCenter,                      fraction = moveFraction,                  ) @@ -326,7 +328,7 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {              val moveAmountForDigit = currentMoveAmount * digitFraction              var moveAmountDeltaForDigit = moveAmountForDigit - currentMoveAmount              if (isMovingToCenter && moveAmountForDigit < 0) moveAmountDeltaForDigit *= -1 -            digitOffsets[mapIndexToId] = moveAmountDeltaForDigit +            digitOffsets[id] = moveAmountDeltaForDigit              invalidate()          }      } @@ -347,7 +349,8 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {                  /* rangeMin= */ 0.0f,                  /* rangeMax= */ 1.0f,                  /* valueMin= */ digitInitialDelay, -                /* valueMax= */ digitInitialDelay + AVAILABLE_ANIMATION_TIME, +                /* valueMax= */ digitInitialDelay + +                    availableAnimationTime(digitalClockTextViewMap.size),                  /* value= */ fraction,              )          ) @@ -357,12 +360,8 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {          val AOD_TRANSITION_DURATION = 750L          val CHARGING_TRANSITION_DURATION = 300L -        // Calculate the positions of all of the digits... -        // Offset each digit by, say, 0.1 -        // This means that each digit needs to move over a slice of "fractions", i.e. digit 0 should -        // move from 0.0 - 0.7, digit 1 from 0.1 - 0.8, digit 2 from 0.2 - 0.9, and digit 3 -        // from 0.3 - 1.0. -        private const val NUM_DIGITS = 4 +        val AOD_HORIZONTAL_TRANSLATE_RATIO = -0.15F +        val AOD_VERTICAL_TRANSLATE_RATIO = 0.075F          // Delays. Each digit's animation should have a slight delay, so we get a nice          // "stepping" effect. When moving right, the second digit of the hour should move first. @@ -387,7 +386,9 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {          // Total available transition time for each digit, taking into account the step. If step is          // 0.1, then digit 0 would animate over 0.0 - 0.7, making availableTime 0.7. -        private const val AVAILABLE_ANIMATION_TIME = 1.0f - MOVE_DIGIT_STEP * (NUM_DIGITS - 1) +        private fun availableAnimationTime(numDigits: Int): Float { +            return 1.0f - MOVE_DIGIT_STEP * (numDigits.toFloat() - 1) +        }          // Add language tags below that do not have vertically mono spaced numerals          private val NON_MONO_VERTICAL_NUMERIC_LINE_SPACING_LANGUAGES = @@ -415,6 +416,14 @@ class FlexClockView(clockCtx: ClockContext) : FrameLayout(clockCtx.context) {                      outPoint.x *= 1                      outPoint.y *= 1                  } +                R.id.HOUR_DIGIT_PAIR -> { +                    outPoint.x *= -1 +                    outPoint.y *= -1 +                } +                R.id.MINUTE_DIGIT_PAIR -> { +                    outPoint.x *= -1 +                    outPoint.y *= 1 +                }              }              return outPoint          } diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt index db39162205b2..9bbdb59283a4 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt @@ -287,6 +287,7 @@ open class SimpleDigitalClockTextView(clockCtx: ClockContext, attrs: AttributeSe                  targetTextBounds,              )          } +          if (layout == null) {              requestLayout()          } else {  |