Loading libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelperTest.kt +5 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.Activity import android.app.ActivityManager import android.content.ComponentName import android.content.Context import android.content.res.Configuration import android.graphics.Insets import android.graphics.Outline import android.graphics.Rect Loading Loading @@ -149,9 +150,12 @@ class BubbleBarAnimationHelperTest { @Test fun animateSwitch_bubbleToBubble_handleColorTransferred() { val fromBubble = createBubble(key = "from").initialize(container) val uiMode = context.getResources().getConfiguration().uiMode and Configuration.UI_MODE_NIGHT_MASK val isSystemDark = uiMode.toInt() == Configuration.UI_MODE_NIGHT_YES fromBubble.bubbleBarExpandedView!! .handleView .updateHandleColor(/* isRegionDark= */ true, /* animated= */ false) .updateHandleColor(/* isRegionDark= */ isSystemDark, /* animated= */ false) val toBubble = createBubble(key = "to").initialize(container) activityScenario.onActivity { Loading libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml +3 −3 Original line number Diff line number Diff line Loading @@ -22,10 +22,10 @@ android:clipChildren="false" android:id="@+id/bubble_expanded_view"> <com.android.wm.shell.bubbles.bar.BubbleBarHandleView android:id="@+id/bubble_bar_handle_view" <com.android.wm.shell.bubbles.bar.BubbleBarCaptionView android:id="@+id/bubble_bar_caption_view" android:layout_height="@dimen/bubble_bar_expanded_view_caption_height" android:layout_width="@dimen/bubble_bar_expanded_view_caption_width" android:layout_width="@dimen/bubble_bar_expanded_view_width" android:layout_gravity="top|center_horizontal" /> </com.android.wm.shell.bubbles.bar.BubbleBarExpandedView> libs/WindowManager/Shell/res/values/dimen.xml +2 −2 Original line number Diff line number Diff line Loading @@ -260,10 +260,10 @@ <dimen name="bubble_popup_elevation">2dp</dimen> <!-- The size of the caption bar inset at the top of bubble bar expanded view. --> <dimen name="bubble_bar_expanded_view_caption_height">36dp</dimen> <!-- The width of the caption bar at the top of bubble bar expanded view. --> <dimen name="bubble_bar_expanded_view_caption_width">80dp</dimen> <!-- The height of the handle shown for the caption menu in the bubble bar expanded view. --> <dimen name="bubble_bar_expanded_view_handle_height">4dp</dimen> <!-- The width of the handle shown for the caption menu in the bubble bar expanded view. --> <dimen name="bubble_bar_expanded_view_handle_width">80dp</dimen> <!-- Width of the expanded bubble bar view shown when the bubble is expanded. --> <dimen name="bubble_bar_expanded_view_width">412dp</dimen> <!-- Offset of the expanded view when it starts sliding in as part of the switch animation --> Loading libs/WindowManager/Shell/res/values/ids.xml +2 −0 Original line number Diff line number Diff line Loading @@ -48,7 +48,9 @@ <item type="id" name="action_move_bubble_bar_left"/> <item type="id" name="action_move_bubble_bar_right"/> <!-- Views for bubbles. --> <item type="id" name="dismiss_view"/> <item type="id" name="bubble_bar_handle_view"/> <!-- Accessibility actions for desktop windowing. --> <item type="id" name="action_snap_left"/> Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarCaptionView.java 0 → 100644 +104 −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.bubbles.bar; import android.content.Context; import android.content.res.Configuration; import android.graphics.Color; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; import androidx.annotation.Nullable; import com.android.wm.shell.R; /** * A view that acts as a caption area for the {@link BubbleBarExpandedView}, containing the handle. */ public class BubbleBarCaptionView extends FrameLayout { public static final int CAPTION_ELEVATION = 1; private final View mBackgroundView; private int mBackgroundColor; private final BubbleBarHandleView mHandleView; public BubbleBarCaptionView(Context context) { this(context, null /* attrs */); } public BubbleBarCaptionView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0 /* defStyleAttr */); } public BubbleBarCaptionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0 /* defStyleRes */); } public BubbleBarCaptionView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); // Add the background view. mBackgroundView = new View(context); addView(mBackgroundView, new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); // Add the handle view. mHandleView = new BubbleBarHandleView(context); mHandleView.setId(R.id.bubble_bar_handle_view); final int handleWidth = getResources().getDimensionPixelSize( R.dimen.bubble_bar_expanded_view_handle_width); final LayoutParams handleLp = new LayoutParams(handleWidth, LayoutParams.MATCH_PARENT); handleLp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; addView(mHandleView, handleLp); // Set background color with an initial color based on the system theme after both views // have been added so that the caption and handle color can be updated if needed. final boolean isSystemDark = (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; setBackgroundColor(isSystemDark ? Color.BLACK : Color.WHITE); // Elevation needs to be set to draw the handle and caption on top of task view. setElevation(CAPTION_ELEVATION); } public BubbleBarHandleView getHandleView() { return mHandleView; } public int getBackgroundColor() { return mBackgroundColor; } /** Sets the background color of the caption bar. */ public void setBackgroundColor(int color) { if (mBackgroundView != null && color != mBackgroundColor) { mBackgroundView.setBackgroundColor(color); mBackgroundColor = color; if (mHandleView != null) { boolean isRegionDark = Color.valueOf(color).luminance() < 0.5; // Only animate the color change if the view is already attached to a window. // During initial inflation (in the constructor), this will be false. mHandleView.updateHandleColor(isRegionDark, isAttachedToWindow() /* animated */); } } } } Loading
libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelperTest.kt +5 −1 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import android.app.Activity import android.app.ActivityManager import android.content.ComponentName import android.content.Context import android.content.res.Configuration import android.graphics.Insets import android.graphics.Outline import android.graphics.Rect Loading Loading @@ -149,9 +150,12 @@ class BubbleBarAnimationHelperTest { @Test fun animateSwitch_bubbleToBubble_handleColorTransferred() { val fromBubble = createBubble(key = "from").initialize(container) val uiMode = context.getResources().getConfiguration().uiMode and Configuration.UI_MODE_NIGHT_MASK val isSystemDark = uiMode.toInt() == Configuration.UI_MODE_NIGHT_YES fromBubble.bubbleBarExpandedView!! .handleView .updateHandleColor(/* isRegionDark= */ true, /* animated= */ false) .updateHandleColor(/* isRegionDark= */ isSystemDark, /* animated= */ false) val toBubble = createBubble(key = "to").initialize(container) activityScenario.onActivity { Loading
libs/WindowManager/Shell/res/layout/bubble_bar_expanded_view.xml +3 −3 Original line number Diff line number Diff line Loading @@ -22,10 +22,10 @@ android:clipChildren="false" android:id="@+id/bubble_expanded_view"> <com.android.wm.shell.bubbles.bar.BubbleBarHandleView android:id="@+id/bubble_bar_handle_view" <com.android.wm.shell.bubbles.bar.BubbleBarCaptionView android:id="@+id/bubble_bar_caption_view" android:layout_height="@dimen/bubble_bar_expanded_view_caption_height" android:layout_width="@dimen/bubble_bar_expanded_view_caption_width" android:layout_width="@dimen/bubble_bar_expanded_view_width" android:layout_gravity="top|center_horizontal" /> </com.android.wm.shell.bubbles.bar.BubbleBarExpandedView>
libs/WindowManager/Shell/res/values/dimen.xml +2 −2 Original line number Diff line number Diff line Loading @@ -260,10 +260,10 @@ <dimen name="bubble_popup_elevation">2dp</dimen> <!-- The size of the caption bar inset at the top of bubble bar expanded view. --> <dimen name="bubble_bar_expanded_view_caption_height">36dp</dimen> <!-- The width of the caption bar at the top of bubble bar expanded view. --> <dimen name="bubble_bar_expanded_view_caption_width">80dp</dimen> <!-- The height of the handle shown for the caption menu in the bubble bar expanded view. --> <dimen name="bubble_bar_expanded_view_handle_height">4dp</dimen> <!-- The width of the handle shown for the caption menu in the bubble bar expanded view. --> <dimen name="bubble_bar_expanded_view_handle_width">80dp</dimen> <!-- Width of the expanded bubble bar view shown when the bubble is expanded. --> <dimen name="bubble_bar_expanded_view_width">412dp</dimen> <!-- Offset of the expanded view when it starts sliding in as part of the switch animation --> Loading
libs/WindowManager/Shell/res/values/ids.xml +2 −0 Original line number Diff line number Diff line Loading @@ -48,7 +48,9 @@ <item type="id" name="action_move_bubble_bar_left"/> <item type="id" name="action_move_bubble_bar_right"/> <!-- Views for bubbles. --> <item type="id" name="dismiss_view"/> <item type="id" name="bubble_bar_handle_view"/> <!-- Accessibility actions for desktop windowing. --> <item type="id" name="action_snap_left"/> Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/bar/BubbleBarCaptionView.java 0 → 100644 +104 −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.bubbles.bar; import android.content.Context; import android.content.res.Configuration; import android.graphics.Color; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; import androidx.annotation.Nullable; import com.android.wm.shell.R; /** * A view that acts as a caption area for the {@link BubbleBarExpandedView}, containing the handle. */ public class BubbleBarCaptionView extends FrameLayout { public static final int CAPTION_ELEVATION = 1; private final View mBackgroundView; private int mBackgroundColor; private final BubbleBarHandleView mHandleView; public BubbleBarCaptionView(Context context) { this(context, null /* attrs */); } public BubbleBarCaptionView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0 /* defStyleAttr */); } public BubbleBarCaptionView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, 0 /* defStyleRes */); } public BubbleBarCaptionView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); // Add the background view. mBackgroundView = new View(context); addView(mBackgroundView, new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); // Add the handle view. mHandleView = new BubbleBarHandleView(context); mHandleView.setId(R.id.bubble_bar_handle_view); final int handleWidth = getResources().getDimensionPixelSize( R.dimen.bubble_bar_expanded_view_handle_width); final LayoutParams handleLp = new LayoutParams(handleWidth, LayoutParams.MATCH_PARENT); handleLp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; addView(mHandleView, handleLp); // Set background color with an initial color based on the system theme after both views // have been added so that the caption and handle color can be updated if needed. final boolean isSystemDark = (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES; setBackgroundColor(isSystemDark ? Color.BLACK : Color.WHITE); // Elevation needs to be set to draw the handle and caption on top of task view. setElevation(CAPTION_ELEVATION); } public BubbleBarHandleView getHandleView() { return mHandleView; } public int getBackgroundColor() { return mBackgroundColor; } /** Sets the background color of the caption bar. */ public void setBackgroundColor(int color) { if (mBackgroundView != null && color != mBackgroundColor) { mBackgroundView.setBackgroundColor(color); mBackgroundColor = color; if (mHandleView != null) { boolean isRegionDark = Color.valueOf(color).luminance() < 0.5; // Only animate the color change if the view is already attached to a window. // During initial inflation (in the constructor), this will be false. mHandleView.updateHandleColor(isRegionDark, isAttachedToWindow() /* animated */); } } } }