Loading libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml +83 −35 Original line number Diff line number Diff line Loading @@ -46,17 +46,10 @@ android:contentDescription="@string/app_icon_text" android:importantForAccessibility="no"/> <TextView <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/application_name" android:layout_width="0dp" android:layout_height="wrap_content" tools:text="Gmail" android:textColor="@androidprv:color/materialColorOnSurface" android:textSize="14sp" android:textFontWeight="500" android:lineHeight="20dp" android:textStyle="normal" android:layout_weight="1"/> style="@style/DesktopModeHandleMenuActionButtonTextView"/> <com.android.wm.shell.windowdecor.HandleMenuImageButton android:id="@+id/collapse_menu_button" Loading Loading @@ -133,37 +126,77 @@ android:elevation="@dimen/desktop_mode_handle_menu_pill_elevation" android:background="@drawable/desktop_mode_decor_handle_menu_background"> <Button <LinearLayout android:id="@+id/screenshot_button" android:contentDescription="@string/screenshot_text" style="@style/DesktopModeHandleMenuActionButtonLayout"> <ImageView android:id="@+id/image" android:src="@drawable/desktop_mode_ic_handle_menu_screenshot" android:importantForAccessibility="no" style="@style/DesktopModeHandleMenuActionButtonImage"/> <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/label" android:text="@string/screenshot_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_screenshot" android:drawableTint="@androidprv:color/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton"/> style="@style/DesktopModeHandleMenuActionButtonTextView"/> </LinearLayout> <Button <LinearLayout android:id="@+id/new_window_button" android:contentDescription="@string/new_window_text" style="@style/DesktopModeHandleMenuActionButtonLayout"> <ImageView android:id="@+id/image" android:src="@drawable/desktop_mode_ic_handle_menu_new_window" android:importantForAccessibility="no" style="@style/DesktopModeHandleMenuActionButtonImage"/> <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/label" android:text="@string/new_window_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_new_window" android:drawableTint="@androidprv:color/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton" /> style="@style/DesktopModeHandleMenuActionButtonTextView"/> </LinearLayout> <Button <LinearLayout android:id="@+id/manage_windows_button" android:contentDescription="@string/manage_windows_text" style="@style/DesktopModeHandleMenuActionButtonLayout"> <ImageView android:id="@+id/image" android:src="@drawable/desktop_mode_ic_handle_menu_manage_windows" android:importantForAccessibility="no" style="@style/DesktopModeHandleMenuActionButtonImage"/> <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/label" android:text="@string/manage_windows_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_manage_windows" android:drawableTint="@androidprv:color/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton" /> style="@style/DesktopModeHandleMenuActionButtonTextView"/> </LinearLayout> <Button <LinearLayout android:id="@+id/change_aspect_ratio_button" android:contentDescription="@string/change_aspect_ratio_text" style="@style/DesktopModeHandleMenuActionButtonLayout"> <ImageView android:id="@+id/image" android:src="@drawable/desktop_mode_ic_handle_menu_change_aspect_ratio" android:importantForAccessibility="no" style="@style/DesktopModeHandleMenuActionButtonImage"/> <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/label" android:text="@string/change_aspect_ratio_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_change_aspect_ratio" android:drawableTint="@androidprv:color/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton" /> style="@style/DesktopModeHandleMenuActionButtonTextView"/> </LinearLayout> </LinearLayout> <LinearLayout Loading @@ -176,22 +209,37 @@ android:elevation="@dimen/desktop_mode_handle_menu_pill_elevation" android:background="@drawable/desktop_mode_decor_handle_menu_background"> <Button <LinearLayout android:id="@+id/open_in_app_or_browser_button" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginEnd="8dp" android:gravity="start|center_vertical" android:paddingStart="16dp" android:contentDescription="@string/open_in_browser_text" android:background="?android:selectableItemBackground"> <ImageView android:id="@+id/image" android:src="@drawable/desktop_mode_ic_handle_menu_open_in_browser" android:importantForAccessibility="no" style="@style/DesktopModeHandleMenuActionButtonImage"/> <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/label" android:text="@string/open_in_browser_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_open_in_browser" android:drawableTint="@androidprv:color/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton"/> style="@style/DesktopModeHandleMenuActionButtonTextView"/> </LinearLayout> <ImageButton android:id="@+id/open_by_default_button" android:layout_width="20dp" android:layout_height="20dp" android:layout_gravity="end|center_vertical" android:layout_marginStart="8dp" android:layout_marginEnd="16dp" android:layout_marginStart="10dp" android:contentDescription="@string/open_by_default_settings_text" android:src="@drawable/desktop_mode_ic_handle_menu_open_by_default_settings" android:tint="@androidprv:color/materialColorOnSurface"/> Loading libs/WindowManager/Shell/res/values/styles.xml +22 −7 Original line number Diff line number Diff line Loading @@ -40,17 +40,32 @@ <item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item> </style> <style name="DesktopModeHandleMenuActionButton"> <style name="DesktopModeHandleMenuActionButtonLayout"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">52dp</item> <item name="android:layout_weight">1</item> <item name="android:gravity">start|center_vertical</item> <item name="android:paddingStart">16dp</item> <item name="android:paddingEnd">0dp</item> <item name="android:paddingHorizontal">16dp</item> <item name="android:background">?android:selectableItemBackground</item> </style> <style name="DesktopModeHandleMenuActionButtonImage"> <item name="android:layout_width">20dp</item> <item name="android:layout_height">20dp</item> <item name="android:layout_marginEnd">16dp</item> </style> <style name="DesktopModeHandleMenuActionButtonTextView"> <item name="android:layout_width">0dp</item> <item name="android:layout_height">wrap_content</item> <item name="android:layout_weight">1</item> <item name="android:textSize">14sp</item> <item name="android:lineHeight">20sp</item> <item name="android:textFontWeight">500</item> <item name="android:textColor">@androidprv:color/materialColorOnSurface</item> <item name="android:drawablePadding">16dp</item> <item name="android:background">?android:selectableItemBackground</item> <item name="android:ellipsize">marquee</item> <item name="android:scrollHorizontally">true</item> <item name="android:singleLine">true</item> </style> <style name="DesktopModeHandleMenuWindowingButton"> Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt +22 −12 Original line number Diff line number Diff line Loading @@ -473,7 +473,7 @@ class HandleMenu( @VisibleForTesting val appIconView = appInfoPill.requireViewById<ImageView>(R.id.application_icon) @VisibleForTesting val appNameView = appInfoPill.requireViewById<TextView>(R.id.application_name) val appNameView = appInfoPill.requireViewById<MarqueedTextView>(R.id.application_name) // Windowing Pill. private val windowingPill = rootView.requireViewById<View>(R.id.windowing_pill) Loading @@ -486,17 +486,17 @@ class HandleMenu( // More Actions Pill. private val moreActionsPill = rootView.requireViewById<View>(R.id.more_actions_pill) private val screenshotBtn = moreActionsPill.requireViewById<Button>(R.id.screenshot_button) private val newWindowBtn = moreActionsPill.requireViewById<Button>(R.id.new_window_button) private val screenshotBtn = moreActionsPill.requireViewById<View>(R.id.screenshot_button) private val newWindowBtn = moreActionsPill.requireViewById<View>(R.id.new_window_button) private val manageWindowBtn = moreActionsPill .requireViewById<Button>(R.id.manage_windows_button) .requireViewById<View>(R.id.manage_windows_button) private val changeAspectRatioBtn = moreActionsPill .requireViewById<Button>(R.id.change_aspect_ratio_button) .requireViewById<View>(R.id.change_aspect_ratio_button) // Open in Browser/App Pill. private val openInAppOrBrowserPill = rootView.requireViewById<View>( R.id.open_in_app_or_browser_pill) private val openInAppOrBrowserBtn = openInAppOrBrowserPill.requireViewById<Button>( private val openInAppOrBrowserBtn = openInAppOrBrowserPill.requireViewById<View>( R.id.open_in_app_or_browser_button) private val openByDefaultBtn = openInAppOrBrowserPill.requireViewById<ImageButton>( R.id.open_by_default_button) Loading Loading @@ -658,6 +658,7 @@ class HandleMenu( this.taskInfo = this@HandleMenuView.taskInfo } appNameView.setTextColor(style.textColor) appNameView.startMarquee() } private fun bindWindowingPill(style: MenuStyle) { Loading Loading @@ -693,11 +694,15 @@ class HandleMenu( ).forEach { val button = it.first val shouldShow = it.second button.apply { isGone = !shouldShow val label = button.requireViewById<MarqueedTextView>(R.id.label) val image = button.requireViewById<ImageView>(R.id.image) button.isGone = !shouldShow label.apply { setTextColor(style.textColor) compoundDrawableTintList = ColorStateList.valueOf(style.textColor) startMarquee() } image.imageTintList = ColorStateList.valueOf(style.textColor) } } Loading @@ -712,12 +717,17 @@ class HandleMenu( } else { getString(R.string.open_in_browser_text) } openInAppOrBrowserBtn.apply { val label = openInAppOrBrowserBtn.requireViewById<MarqueedTextView>(R.id.label) val image = openInAppOrBrowserBtn.requireViewById<ImageView>(R.id.image) openInAppOrBrowserBtn.contentDescription = btnText label.apply { text = btnText contentDescription = btnText setTextColor(style.textColor) compoundDrawableTintList = ColorStateList.valueOf(style.textColor) startMarquee() } image.imageTintList = ColorStateList.valueOf(style.textColor) openByDefaultBtn.isGone = isBrowserApp openByDefaultBtn.imageTintList = ColorStateList.valueOf(style.textColor) } Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuAnimator.kt +1 −1 Original line number Diff line number Diff line Loading @@ -327,7 +327,7 @@ class HandleMenuAnimator( } // Open in Browser Button Opacity Animation val button = openInAppOrBrowserPill.requireViewById<Button>(R.id.open_in_app_or_browser_button) val button = openInAppOrBrowserPill.requireViewById<View>(R.id.open_in_app_or_browser_button) animators += ObjectAnimator.ofFloat(button, ALPHA, 1f).apply { startDelay = BODY_ALPHA_OPEN_DELAY Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MarqueedTextView.kt 0 → 100644 +48 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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. */ package com.android.wm.shell.windowdecor import android.content.Context import android.util.AttributeSet import android.widget.TextView /** A custom [TextView] that allows better control over marquee animation used to ellipsize text. */ class MarqueedTextView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.textViewStyle ) : TextView(context, attrs, defStyleAttr) { /** * Starts marquee animation if the layout attributes for this object include * `android:ellipsize=marquee`, `android:singleLine=true`, and * `android:scrollHorizontally=true`. */ override public fun startMarquee() { super.startMarquee() } /** * Must always return [true] since [TextView.startMarquee()] requires view to be selected or * focused in order to start the marquee animation. * * We are not using [TextView.setSelected()] as this would dispatch undesired accessibility * events. */ override fun isSelected() : Boolean { return true } } Loading
libs/WindowManager/Shell/res/layout/desktop_mode_window_decor_handle_menu.xml +83 −35 Original line number Diff line number Diff line Loading @@ -46,17 +46,10 @@ android:contentDescription="@string/app_icon_text" android:importantForAccessibility="no"/> <TextView <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/application_name" android:layout_width="0dp" android:layout_height="wrap_content" tools:text="Gmail" android:textColor="@androidprv:color/materialColorOnSurface" android:textSize="14sp" android:textFontWeight="500" android:lineHeight="20dp" android:textStyle="normal" android:layout_weight="1"/> style="@style/DesktopModeHandleMenuActionButtonTextView"/> <com.android.wm.shell.windowdecor.HandleMenuImageButton android:id="@+id/collapse_menu_button" Loading Loading @@ -133,37 +126,77 @@ android:elevation="@dimen/desktop_mode_handle_menu_pill_elevation" android:background="@drawable/desktop_mode_decor_handle_menu_background"> <Button <LinearLayout android:id="@+id/screenshot_button" android:contentDescription="@string/screenshot_text" style="@style/DesktopModeHandleMenuActionButtonLayout"> <ImageView android:id="@+id/image" android:src="@drawable/desktop_mode_ic_handle_menu_screenshot" android:importantForAccessibility="no" style="@style/DesktopModeHandleMenuActionButtonImage"/> <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/label" android:text="@string/screenshot_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_screenshot" android:drawableTint="@androidprv:color/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton"/> style="@style/DesktopModeHandleMenuActionButtonTextView"/> </LinearLayout> <Button <LinearLayout android:id="@+id/new_window_button" android:contentDescription="@string/new_window_text" style="@style/DesktopModeHandleMenuActionButtonLayout"> <ImageView android:id="@+id/image" android:src="@drawable/desktop_mode_ic_handle_menu_new_window" android:importantForAccessibility="no" style="@style/DesktopModeHandleMenuActionButtonImage"/> <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/label" android:text="@string/new_window_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_new_window" android:drawableTint="@androidprv:color/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton" /> style="@style/DesktopModeHandleMenuActionButtonTextView"/> </LinearLayout> <Button <LinearLayout android:id="@+id/manage_windows_button" android:contentDescription="@string/manage_windows_text" style="@style/DesktopModeHandleMenuActionButtonLayout"> <ImageView android:id="@+id/image" android:src="@drawable/desktop_mode_ic_handle_menu_manage_windows" android:importantForAccessibility="no" style="@style/DesktopModeHandleMenuActionButtonImage"/> <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/label" android:text="@string/manage_windows_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_manage_windows" android:drawableTint="@androidprv:color/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton" /> style="@style/DesktopModeHandleMenuActionButtonTextView"/> </LinearLayout> <Button <LinearLayout android:id="@+id/change_aspect_ratio_button" android:contentDescription="@string/change_aspect_ratio_text" style="@style/DesktopModeHandleMenuActionButtonLayout"> <ImageView android:id="@+id/image" android:src="@drawable/desktop_mode_ic_handle_menu_change_aspect_ratio" android:importantForAccessibility="no" style="@style/DesktopModeHandleMenuActionButtonImage"/> <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/label" android:text="@string/change_aspect_ratio_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_change_aspect_ratio" android:drawableTint="@androidprv:color/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton" /> style="@style/DesktopModeHandleMenuActionButtonTextView"/> </LinearLayout> </LinearLayout> <LinearLayout Loading @@ -176,22 +209,37 @@ android:elevation="@dimen/desktop_mode_handle_menu_pill_elevation" android:background="@drawable/desktop_mode_decor_handle_menu_background"> <Button <LinearLayout android:id="@+id/open_in_app_or_browser_button" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:layout_marginEnd="8dp" android:gravity="start|center_vertical" android:paddingStart="16dp" android:contentDescription="@string/open_in_browser_text" android:background="?android:selectableItemBackground"> <ImageView android:id="@+id/image" android:src="@drawable/desktop_mode_ic_handle_menu_open_in_browser" android:importantForAccessibility="no" style="@style/DesktopModeHandleMenuActionButtonImage"/> <com.android.wm.shell.windowdecor.MarqueedTextView android:id="@+id/label" android:text="@string/open_in_browser_text" android:drawableStart="@drawable/desktop_mode_ic_handle_menu_open_in_browser" android:drawableTint="@androidprv:color/materialColorOnSurface" style="@style/DesktopModeHandleMenuActionButton"/> style="@style/DesktopModeHandleMenuActionButtonTextView"/> </LinearLayout> <ImageButton android:id="@+id/open_by_default_button" android:layout_width="20dp" android:layout_height="20dp" android:layout_gravity="end|center_vertical" android:layout_marginStart="8dp" android:layout_marginEnd="16dp" android:layout_marginStart="10dp" android:contentDescription="@string/open_by_default_settings_text" android:src="@drawable/desktop_mode_ic_handle_menu_open_by_default_settings" android:tint="@androidprv:color/materialColorOnSurface"/> Loading
libs/WindowManager/Shell/res/values/styles.xml +22 −7 Original line number Diff line number Diff line Loading @@ -40,17 +40,32 @@ <item name="android:activityCloseExitAnimation">@anim/forced_resizable_exit</item> </style> <style name="DesktopModeHandleMenuActionButton"> <style name="DesktopModeHandleMenuActionButtonLayout"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">52dp</item> <item name="android:layout_weight">1</item> <item name="android:gravity">start|center_vertical</item> <item name="android:paddingStart">16dp</item> <item name="android:paddingEnd">0dp</item> <item name="android:paddingHorizontal">16dp</item> <item name="android:background">?android:selectableItemBackground</item> </style> <style name="DesktopModeHandleMenuActionButtonImage"> <item name="android:layout_width">20dp</item> <item name="android:layout_height">20dp</item> <item name="android:layout_marginEnd">16dp</item> </style> <style name="DesktopModeHandleMenuActionButtonTextView"> <item name="android:layout_width">0dp</item> <item name="android:layout_height">wrap_content</item> <item name="android:layout_weight">1</item> <item name="android:textSize">14sp</item> <item name="android:lineHeight">20sp</item> <item name="android:textFontWeight">500</item> <item name="android:textColor">@androidprv:color/materialColorOnSurface</item> <item name="android:drawablePadding">16dp</item> <item name="android:background">?android:selectableItemBackground</item> <item name="android:ellipsize">marquee</item> <item name="android:scrollHorizontally">true</item> <item name="android:singleLine">true</item> </style> <style name="DesktopModeHandleMenuWindowingButton"> Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt +22 −12 Original line number Diff line number Diff line Loading @@ -473,7 +473,7 @@ class HandleMenu( @VisibleForTesting val appIconView = appInfoPill.requireViewById<ImageView>(R.id.application_icon) @VisibleForTesting val appNameView = appInfoPill.requireViewById<TextView>(R.id.application_name) val appNameView = appInfoPill.requireViewById<MarqueedTextView>(R.id.application_name) // Windowing Pill. private val windowingPill = rootView.requireViewById<View>(R.id.windowing_pill) Loading @@ -486,17 +486,17 @@ class HandleMenu( // More Actions Pill. private val moreActionsPill = rootView.requireViewById<View>(R.id.more_actions_pill) private val screenshotBtn = moreActionsPill.requireViewById<Button>(R.id.screenshot_button) private val newWindowBtn = moreActionsPill.requireViewById<Button>(R.id.new_window_button) private val screenshotBtn = moreActionsPill.requireViewById<View>(R.id.screenshot_button) private val newWindowBtn = moreActionsPill.requireViewById<View>(R.id.new_window_button) private val manageWindowBtn = moreActionsPill .requireViewById<Button>(R.id.manage_windows_button) .requireViewById<View>(R.id.manage_windows_button) private val changeAspectRatioBtn = moreActionsPill .requireViewById<Button>(R.id.change_aspect_ratio_button) .requireViewById<View>(R.id.change_aspect_ratio_button) // Open in Browser/App Pill. private val openInAppOrBrowserPill = rootView.requireViewById<View>( R.id.open_in_app_or_browser_pill) private val openInAppOrBrowserBtn = openInAppOrBrowserPill.requireViewById<Button>( private val openInAppOrBrowserBtn = openInAppOrBrowserPill.requireViewById<View>( R.id.open_in_app_or_browser_button) private val openByDefaultBtn = openInAppOrBrowserPill.requireViewById<ImageButton>( R.id.open_by_default_button) Loading Loading @@ -658,6 +658,7 @@ class HandleMenu( this.taskInfo = this@HandleMenuView.taskInfo } appNameView.setTextColor(style.textColor) appNameView.startMarquee() } private fun bindWindowingPill(style: MenuStyle) { Loading Loading @@ -693,11 +694,15 @@ class HandleMenu( ).forEach { val button = it.first val shouldShow = it.second button.apply { isGone = !shouldShow val label = button.requireViewById<MarqueedTextView>(R.id.label) val image = button.requireViewById<ImageView>(R.id.image) button.isGone = !shouldShow label.apply { setTextColor(style.textColor) compoundDrawableTintList = ColorStateList.valueOf(style.textColor) startMarquee() } image.imageTintList = ColorStateList.valueOf(style.textColor) } } Loading @@ -712,12 +717,17 @@ class HandleMenu( } else { getString(R.string.open_in_browser_text) } openInAppOrBrowserBtn.apply { val label = openInAppOrBrowserBtn.requireViewById<MarqueedTextView>(R.id.label) val image = openInAppOrBrowserBtn.requireViewById<ImageView>(R.id.image) openInAppOrBrowserBtn.contentDescription = btnText label.apply { text = btnText contentDescription = btnText setTextColor(style.textColor) compoundDrawableTintList = ColorStateList.valueOf(style.textColor) startMarquee() } image.imageTintList = ColorStateList.valueOf(style.textColor) openByDefaultBtn.isGone = isBrowserApp openByDefaultBtn.imageTintList = ColorStateList.valueOf(style.textColor) } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenuAnimator.kt +1 −1 Original line number Diff line number Diff line Loading @@ -327,7 +327,7 @@ class HandleMenuAnimator( } // Open in Browser Button Opacity Animation val button = openInAppOrBrowserPill.requireViewById<Button>(R.id.open_in_app_or_browser_button) val button = openInAppOrBrowserPill.requireViewById<View>(R.id.open_in_app_or_browser_button) animators += ObjectAnimator.ofFloat(button, ALPHA, 1f).apply { startDelay = BODY_ALPHA_OPEN_DELAY Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/MarqueedTextView.kt 0 → 100644 +48 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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. */ package com.android.wm.shell.windowdecor import android.content.Context import android.util.AttributeSet import android.widget.TextView /** A custom [TextView] that allows better control over marquee animation used to ellipsize text. */ class MarqueedTextView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = android.R.attr.textViewStyle ) : TextView(context, attrs, defStyleAttr) { /** * Starts marquee animation if the layout attributes for this object include * `android:ellipsize=marquee`, `android:singleLine=true`, and * `android:scrollHorizontally=true`. */ override public fun startMarquee() { super.startMarquee() } /** * Must always return [true] since [TextView.startMarquee()] requires view to be selected or * focused in order to start the marquee animation. * * We are not using [TextView.setSelected()] as this would dispatch undesired accessibility * events. */ override fun isSelected() : Boolean { return true } }