From 612aac88cbdf6482dfdde2eb2fddc5cedf83fdcc Mon Sep 17 00:00:00 2001 From: Jordan Silva Date: Fri, 28 Mar 2025 18:40:45 +0000 Subject: [PATCH] Update marquee to show only when chip is expanded - Introduced title and titleCollapsed to change the text when expanded and collapsed using only 2 dots for truncate the text, similar to ellipsize="marquee". - Removed ellipsize="marquee" from the XML to prevent chip relayout when entering in Overview. See b/406969521. Fix: 406969521 Fix: 403193877 Flag: com.android.launcher3.enable_overview_icon_menu Test: OverviewImageTest Test: OverviewSplitTaskImageTest Change-Id: Ia95eb8b7ec6d22b9d576defe7c66a4950ee1dca3 --- quickstep/res/layout/icon_app_chip_view.xml | 5 +- quickstep/res/values/dimens.xml | 4 + .../quickstep/views/IconAppChipView.kt | 74 +++++++++++-------- 3 files changed, 52 insertions(+), 31 deletions(-) diff --git a/quickstep/res/layout/icon_app_chip_view.xml b/quickstep/res/layout/icon_app_chip_view.xml index 3173528248..0dfe0e493c 100644 --- a/quickstep/res/layout/icon_app_chip_view.xml +++ b/quickstep/res/layout/icon_app_chip_view.xml @@ -57,10 +57,11 @@ android:gravity="start|center_vertical" android:maxLines="1" android:singleLine="true" - android:ellipsize="marquee" + android:ellipsize="none" android:textAlignment="viewStart" android:importantForAccessibility="no" - android:fadingEdge="horizontal" + android:requiresFadingEdge="horizontal" + android:fadingEdgeLength="@dimen/task_thumbnail_icon_menu_text_fading_size" android:marqueeRepeatLimit="1" android:scrollHorizontally="true" style="@style/IconAppChipMenuTextStyle" /> diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 9bde865b2e..640c94ef5d 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -66,6 +66,8 @@ 8dp 8dp + + 12dp 2dp @@ -81,6 +83,8 @@ 44dp 4dp + + 20dp 30dp 18dp diff --git a/quickstep/src/com/android/quickstep/views/IconAppChipView.kt b/quickstep/src/com/android/quickstep/views/IconAppChipView.kt index 307e00cd02..ff9f99fa30 100644 --- a/quickstep/src/com/android/quickstep/views/IconAppChipView.kt +++ b/quickstep/src/com/android/quickstep/views/IconAppChipView.kt @@ -23,7 +23,7 @@ import android.content.Context import android.graphics.Outline import android.graphics.Rect import android.graphics.drawable.Drawable -import android.text.TextUtils +import android.text.TextUtils.TruncateAt import android.util.AttributeSet import android.view.View import android.view.ViewAnimationUtils @@ -87,10 +87,14 @@ constructor( ) // Contents dimensions - private val appNameHorizontalMargin = + private val appNameHorizontalMarginCollapsed = resources.getDimensionPixelSize( R.dimen.task_thumbnail_icon_menu_app_name_margin_horizontal_collapsed ) + private val appNameHorizontalMarginExpanded = + resources.getDimensionPixelSize( + R.dimen.task_thumbnail_icon_menu_app_name_margin_horizontal_expanded + ) private val arrowMarginEnd = resources.getDimensionPixelSize(R.dimen.task_thumbnail_icon_menu_arrow_margin) private val iconViewMarginStart = @@ -148,6 +152,7 @@ constructor( override fun getDrawable(): Drawable? = iconView?.drawable private var currentIconDrawableHash: Int = 0 + override fun setDrawable(icon: Drawable?) { if (icon.hashCode() == currentIconDrawableHash) return iconView?.drawable = icon @@ -209,18 +214,12 @@ constructor( // Layout Params for the collapsed Icon Text View val textMarginStart = - iconMarginStartRelativeToParent + appIconSize + appNameHorizontalMargin + iconMarginStartRelativeToParent + appIconSize + appNameHorizontalMarginCollapsed val iconTextCollapsedParams = appTitle!!.layoutParams as LayoutParams orientationHandler.setIconAppChipChildrenParams(iconTextCollapsedParams, textMarginStart) iconTextCollapsedParams.width = calculateCollapsedTextWidth(collapsedBackgroundBounds.width()) - appTitle!!.layoutParams = iconTextCollapsedParams - // select to enable marquee and disable it when is running test harness. - if (Utilities.isRunningInTestHarness()) { - disableAppTitleMarquee() - } else { - appTitle!!.isSelected = true - } + appTitle?.layoutParams = iconTextCollapsedParams // Layout Params for the Icon Arrow View val iconArrowParams = iconArrowView!!.layoutParams as LayoutParams @@ -240,12 +239,12 @@ constructor( ) } - private fun disableAppTitleMarquee() { + private fun enableMarquee(isEnabled: Boolean) { + // Marquee should not be enabled when is running test harness. + val isMarqueeEnabled = isEnabled && !Utilities.isRunningInTestHarness() appTitle?.let { - it.isHorizontalFadingEdgeEnabled = false - it.ellipsize = TextUtils.TruncateAt.END - it.horizontallyScrolling = false - it.isSelected = false + it.ellipsize = if (isMarqueeEnabled) TruncateAt.MARQUEE else null + it.isSelected = isMarqueeEnabled } } @@ -265,13 +264,21 @@ constructor( iconViewMarginStart - appIconSize - arrowSize - - appNameHorizontalMargin - + appNameHorizontalMarginCollapsed - arrowMarginEnd) val spaceLeftForText = maxWidth - minWidthAllowed - return minOf(collapsedTextWidth, spaceLeftForText) + return minOf(collapsedTextWidth, spaceLeftForText).coerceAtLeast(0) } + private fun calculateExpandedTextWidth(width: Int): Int = + width - + iconViewMarginStart - + iconViewDrawableExpandedSize - + arrowSize - + appNameHorizontalMarginExpanded - + arrowMarginEnd + override fun setIconColorTint(color: Int, amount: Float) { // RecentsView's COLOR_TINT animates between 0 and 0.5f, we want to hide the app chip menu. val colorTintAlpha = Utilities.mapToRange(amount, 0f, 0.5f, 1f, 0f, Interpolators.LINEAR) @@ -339,13 +346,14 @@ constructor( val isRtl = isLayoutRtl bringToFront() // Clip expanded text with reveal animation so it doesn't go beyond the edge of the menu + val expandedAppTitleWidth = calculateExpandedTextWidth(expandedBackgroundBounds.width()) val expandedTextRevealAnim = ViewAnimationUtils.createCircularReveal( appTitle, 0, appTitle!!.height / 2, appTitle!!.width.toFloat(), - expandedMaxTextWidth.toFloat(), + expandedAppTitleWidth.toFloat(), ) // Animate background clipping val backgroundAnimator = @@ -359,9 +367,9 @@ constructor( val iconViewScaling = iconViewDrawableExpandedSize / appIconSize.toFloat() val arrowTranslationX = (expandedBackgroundBounds.right - collapsedBackgroundBounds.right).toFloat() - val iconCenterToTextCollapsed = appIconSize / 2f + appNameHorizontalMargin + val iconCenterToTextCollapsed = appIconSize / 2f + appNameHorizontalMarginCollapsed val iconCenterToTextExpanded = - iconViewDrawableExpandedSize / 2f + appNameHorizontalMargin + iconViewDrawableExpandedSize / 2f + appNameHorizontalMarginCollapsed val textTranslationX = iconCenterToTextExpanded - iconCenterToTextCollapsed val textTranslationXWithRtl = if (isRtl) -textTranslationX else textTranslationX @@ -414,14 +422,23 @@ constructor( if (!animated) animator!!.duration = 0 animator!!.interpolator = Interpolators.EMPHASIZED + + // Increase the chip and appTitle size before the animation starts when it's expanding. + // And decrease the size after the animation when is collapsing. animator!!.addListener( onStart = { - appTitle!!.isSelected = false - if (status == AppChipStatus.Expanded) updateChipSize() + when (status) { + AppChipStatus.Expanded -> updateChipSize() + // Disable marquee before chip is collapsed + AppChipStatus.Collapsed -> enableMarquee(false) + } }, onEnd = { - if (status == AppChipStatus.Collapsed) updateChipSize() - appTitle!!.isSelected = true + when (status) { + AppChipStatus.Collapsed -> updateChipSize() + // Enable marquee after chip is fully expanded + AppChipStatus.Expanded -> enableMarquee(true) + } }, ) animator!!.start() @@ -444,7 +461,7 @@ constructor( when (status) { AppChipStatus.Expanded -> { updateLayoutParams { width = chipWidth } - appTitle!!.updateLayoutParams { width = expandedMaxTextWidth } + appTitle!!.updateLayoutParams { width = calculateExpandedTextWidth(chipWidth) } } AppChipStatus.Collapsed -> { appTitle!!.updateLayoutParams { @@ -491,17 +508,16 @@ constructor( if (mParent == null) return null return when (direction) { FOCUS_RIGHT, - FOCUS_DOWN -> mParent.focusSearch(this, View.FOCUS_FORWARD) + FOCUS_DOWN -> mParent.focusSearch(this, FOCUS_FORWARD) FOCUS_UP, - FOCUS_LEFT -> mParent.focusSearch(this, View.FOCUS_BACKWARD) + FOCUS_LEFT -> mParent.focusSearch(this, FOCUS_BACKWARD) else -> super.focusSearch(direction) } } fun reset() { setText(null) - setDrawable(null) - currentIconDrawableHash = 0 + drawable = null } override fun asView(): View = this