Merge "Inset the bubble bar expanded view instead of drawing our own header" into udc-qpr-dev

This commit is contained in:
Mady Mellor
2023-07-06 16:21:50 +00:00
committed by Android (Google) Code Review
5 changed files with 95 additions and 61 deletions

View File

@@ -228,12 +228,12 @@
<dimen name="bubble_user_education_stack_padding">16dp</dimen> <dimen name="bubble_user_education_stack_padding">16dp</dimen>
<!-- Size of the bubble bar (height), should match transient_taskbar_size in Launcher. --> <!-- Size of the bubble bar (height), should match transient_taskbar_size in Launcher. -->
<dimen name="bubblebar_size">72dp</dimen> <dimen name="bubblebar_size">72dp</dimen>
<!-- The size of the drag handle / menu shown along with a bubble bar expanded view. --> <!-- The size of the caption bar inset at the top of bubble bar expanded view. -->
<dimen name="bubble_bar_expanded_view_handle_size">40dp</dimen> <dimen name="bubble_bar_expanded_view_caption_height">32dp</dimen>
<!-- The width of the drag handle shown along with a bubble bar expanded view. --> <!-- The height of the dots shown for the caption menu in the bubble bar expanded view.. -->
<dimen name="bubble_bar_expanded_view_handle_width">128dp</dimen> <dimen name="bubble_bar_expanded_view_caption_dot_size">4dp</dimen>
<!-- The height of the drag handle shown along with a bubble bar expanded view. --> <!-- The spacing between the dots for the caption menu in the bubble bar expanded view.. -->
<dimen name="bubble_bar_expanded_view_handle_height">4dp</dimen> <dimen name="bubble_bar_expanded_view_caption_dot_spacing">4dp</dimen>
<!-- Minimum width of the bubble bar manage menu. --> <!-- Minimum width of the bubble bar manage menu. -->
<dimen name="bubble_bar_manage_menu_min_width">200dp</dimen> <dimen name="bubble_bar_manage_menu_min_width">200dp</dimen>
<!-- Size of the dismiss icon in the bubble bar manage menu. --> <!-- Size of the dismiss icon in the bubble bar manage menu. -->

View File

@@ -25,6 +25,8 @@ import android.graphics.PointF;
import android.util.Log; import android.util.Log;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.animation.PhysicsAnimator; import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.bubbles.BubbleOverflow; import com.android.wm.shell.bubbles.BubbleOverflow;
@@ -111,7 +113,8 @@ public class BubbleBarAnimationHelper {
/** /**
* Animates the provided bubble's expanded view to the expanded state. * Animates the provided bubble's expanded view to the expanded state.
*/ */
public void animateExpansion(BubbleViewProvider expandedBubble) { public void animateExpansion(BubbleViewProvider expandedBubble,
@Nullable Runnable afterAnimation) {
mExpandedBubble = expandedBubble; mExpandedBubble = expandedBubble;
if (mExpandedBubble == null) { if (mExpandedBubble == null) {
return; return;
@@ -160,6 +163,9 @@ public class BubbleBarAnimationHelper {
bev.setAnimationMatrix(null); bev.setAnimationMatrix(null);
updateExpandedView(); updateExpandedView();
bev.setSurfaceZOrderedOnTop(false); bev.setSurfaceZOrderedOnTop(false);
if (afterAnimation != null) {
afterAnimation.run();
}
}) })
.start(); .start();
} }

View File

@@ -16,12 +16,12 @@
package com.android.wm.shell.bubbles.bar; package com.android.wm.shell.bubbles.bar;
import android.annotation.ColorInt;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Insets;
import android.graphics.Outline; import android.graphics.Outline;
import android.graphics.Rect; import android.graphics.Rect;
import android.util.AttributeSet; import android.util.AttributeSet;
@@ -63,7 +63,8 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
private @Nullable TaskView mTaskView; private @Nullable TaskView mTaskView;
private @Nullable BubbleOverflowContainerView mOverflowView; private @Nullable BubbleOverflowContainerView mOverflowView;
private int mHandleHeight; private int mCaptionHeight;
private int mBackgroundColor; private int mBackgroundColor;
private float mCornerRadius = 0f; private float mCornerRadius = 0f;
@@ -97,8 +98,8 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
super.onFinishInflate(); super.onFinishInflate();
Context context = getContext(); Context context = getContext();
setElevation(getResources().getDimensionPixelSize(R.dimen.bubble_elevation)); setElevation(getResources().getDimensionPixelSize(R.dimen.bubble_elevation));
mHandleHeight = context.getResources().getDimensionPixelSize( mCaptionHeight = context.getResources().getDimensionPixelSize(
R.dimen.bubble_bar_expanded_view_handle_size); R.dimen.bubble_bar_expanded_view_caption_height);
addView(mHandleView); addView(mHandleView);
applyThemeAttrs(); applyThemeAttrs();
setClipToOutline(true); setClipToOutline(true);
@@ -136,6 +137,9 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
addView(mTaskView); addView(mTaskView);
mTaskView.setEnableSurfaceClipping(true); mTaskView.setEnableSurfaceClipping(true);
mTaskView.setCornerRadius(mCornerRadius); mTaskView.setCornerRadius(mCornerRadius);
// Handle view needs to draw on top of task view.
bringChildToFront(mHandleView);
} }
mMenuViewController = new BubbleBarMenuViewController(mContext, this); mMenuViewController = new BubbleBarMenuViewController(mContext, this);
mMenuViewController.setListener(new BubbleBarMenuViewController.Listener() { mMenuViewController.setListener(new BubbleBarMenuViewController.Listener() {
@@ -169,6 +173,10 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
}); });
} }
public BubbleBarHandleView getHandleView() {
return mHandleView;
}
// TODO (b/275087636): call this when theme/config changes // TODO (b/275087636): call this when theme/config changes
/** Updates the view based on the current theme. */ /** Updates the view based on the current theme. */
public void applyThemeAttrs() { public void applyThemeAttrs() {
@@ -183,12 +191,12 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
ta.recycle(); ta.recycle();
mHandleHeight = getResources().getDimensionPixelSize( mCaptionHeight = getResources().getDimensionPixelSize(
R.dimen.bubble_bar_expanded_view_handle_size); R.dimen.bubble_bar_expanded_view_caption_height);
if (mTaskView != null) { if (mTaskView != null) {
mTaskView.setCornerRadius(mCornerRadius); mTaskView.setCornerRadius(mCornerRadius);
updateHandleAndBackgroundColor(true /* animated */); updateHandleColor(true /* animated */);
} }
} }
@@ -196,13 +204,12 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec);
int menuViewHeight = Math.min(mHandleHeight, height); int menuViewHeight = Math.min(mCaptionHeight, height);
measureChild(mHandleView, widthMeasureSpec, MeasureSpec.makeMeasureSpec(menuViewHeight, measureChild(mHandleView, widthMeasureSpec, MeasureSpec.makeMeasureSpec(menuViewHeight,
MeasureSpec.getMode(heightMeasureSpec))); MeasureSpec.getMode(heightMeasureSpec)));
if (mTaskView != null) { if (mTaskView != null) {
int taskViewHeight = height - menuViewHeight; measureChild(mTaskView, widthMeasureSpec, MeasureSpec.makeMeasureSpec(height,
measureChild(mTaskView, widthMeasureSpec, MeasureSpec.makeMeasureSpec(taskViewHeight,
MeasureSpec.getMode(heightMeasureSpec))); MeasureSpec.getMode(heightMeasureSpec)));
} }
} }
@@ -210,19 +217,20 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
@Override @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) { protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b); super.onLayout(changed, l, t, r, b);
// Drag handle above final int captionBottom = t + mCaptionHeight;
final int dragHandleBottom = t + mHandleView.getMeasuredHeight();
mHandleView.layout(l, t, r, dragHandleBottom);
if (mTaskView != null) { if (mTaskView != null) {
mTaskView.layout(l, dragHandleBottom, r, mTaskView.layout(l, t, r,
dragHandleBottom + mTaskView.getMeasuredHeight()); t + mTaskView.getMeasuredHeight());
mTaskView.setCaptionInsets(Insets.of(0, mCaptionHeight, 0, 0));
} }
// Handle draws on top of task view in the caption area.
mHandleView.layout(l, t, r, captionBottom);
} }
@Override @Override
public void onTaskCreated() { public void onTaskCreated() {
setContentVisibility(true); setContentVisibility(true);
updateHandleAndBackgroundColor(false /* animated */); updateHandleColor(false /* animated */);
} }
@Override @Override
@@ -298,33 +306,20 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
} }
/** /**
* Updates the background color to match with task view status/bg color, and sets handle color * Updates the handle color based on the task view status bar or background color; if those
* to contrast with the background * are transparent it defaults to the background color pulled from system theme attributes.
*/ */
private void updateHandleAndBackgroundColor(boolean animated) { private void updateHandleColor(boolean animated) {
if (mTaskView == null) return; if (mTaskView == null || mTaskView.getTaskInfo() == null) return;
final int color = getTaskViewColor(); int color = mBackgroundColor;
final boolean isRegionDark = Color.luminance(color) <= 0.5;
mHandleView.updateHandleColor(isRegionDark, animated);
setBackgroundColor(color);
}
/**
* Retrieves task view status/nav bar color or background if available
*
* TODO (b/283075226): Update with color sampling when
* RegionSamplingHelper or alternative is available
*/
private @ColorInt int getTaskViewColor() {
if (mTaskView == null || mTaskView.getTaskInfo() == null) return mBackgroundColor;
ActivityManager.TaskDescription taskDescription = mTaskView.getTaskInfo().taskDescription; ActivityManager.TaskDescription taskDescription = mTaskView.getTaskInfo().taskDescription;
if (taskDescription.getStatusBarColor() != Color.TRANSPARENT) { if (taskDescription.getStatusBarColor() != Color.TRANSPARENT) {
return taskDescription.getStatusBarColor(); color = taskDescription.getStatusBarColor();
} else if (taskDescription.getBackgroundColor() != Color.TRANSPARENT) { } else if (taskDescription.getBackgroundColor() != Color.TRANSPARENT) {
return taskDescription.getBackgroundColor(); color = taskDescription.getBackgroundColor();
} else {
return mBackgroundColor;
} }
final boolean isRegionDark = Color.luminance(color) <= 0.5;
mHandleView.updateHandleColor(isRegionDark, animated);
} }
/** /**

View File

@@ -21,7 +21,8 @@ import android.animation.ObjectAnimator;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.content.Context; import android.content.Context;
import android.graphics.Outline; import android.graphics.Outline;
import android.graphics.Rect; import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.view.ViewOutlineProvider; import android.view.ViewOutlineProvider;
@@ -37,8 +38,12 @@ import com.android.wm.shell.R;
public class BubbleBarHandleView extends View { public class BubbleBarHandleView extends View {
private static final long COLOR_CHANGE_DURATION = 120; private static final long COLOR_CHANGE_DURATION = 120;
private int mHandleWidth; // The handle view is currently rendered as 3 evenly spaced dots.
private int mHandleHeight; private int mDotSize;
private int mDotSpacing;
// Path used to draw the dots
private final Path mPath = new Path();
private @ColorInt int mHandleLightColor; private @ColorInt int mHandleLightColor;
private @ColorInt int mHandleDarkColor; private @ColorInt int mHandleDarkColor;
private @Nullable ObjectAnimator mColorChangeAnim; private @Nullable ObjectAnimator mColorChangeAnim;
@@ -58,11 +63,10 @@ public class BubbleBarHandleView extends View {
public BubbleBarHandleView(Context context, AttributeSet attrs, int defStyleAttr, public BubbleBarHandleView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) { int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes); super(context, attrs, defStyleAttr, defStyleRes);
mDotSize = getResources().getDimensionPixelSize(
mHandleWidth = getResources().getDimensionPixelSize( R.dimen.bubble_bar_expanded_view_caption_dot_size);
R.dimen.bubble_bar_expanded_view_handle_width); mDotSpacing = getResources().getDimensionPixelSize(
mHandleHeight = getResources().getDimensionPixelSize( R.dimen.bubble_bar_expanded_view_caption_dot_spacing);
R.dimen.bubble_bar_expanded_view_handle_height);
mHandleLightColor = ContextCompat.getColor(getContext(), mHandleLightColor = ContextCompat.getColor(getContext(),
R.color.bubble_bar_expanded_view_handle_light); R.color.bubble_bar_expanded_view_handle_light);
mHandleDarkColor = ContextCompat.getColor(getContext(), mHandleDarkColor = ContextCompat.getColor(getContext(),
@@ -74,13 +78,26 @@ public class BubbleBarHandleView extends View {
public void getOutline(View view, Outline outline) { public void getOutline(View view, Outline outline) {
final int handleCenterX = view.getWidth() / 2; final int handleCenterX = view.getWidth() / 2;
final int handleCenterY = view.getHeight() / 2; final int handleCenterY = view.getHeight() / 2;
final float handleRadius = mHandleHeight / 2f; final int handleTotalWidth = mDotSize * 3 + mDotSpacing * 2;
Rect handleBounds = new Rect( final int handleLeft = handleCenterX - handleTotalWidth / 2;
handleCenterX - mHandleWidth / 2, final int handleTop = handleCenterY - mDotSize / 2;
handleCenterY - mHandleHeight / 2, final int handleBottom = handleTop + mDotSize;
handleCenterX + mHandleWidth / 2, RectF dot1 = new RectF(
handleCenterY + mHandleHeight / 2); handleLeft, handleTop,
outline.setRoundRect(handleBounds, handleRadius); handleLeft + mDotSize, handleBottom);
RectF dot2 = new RectF(
dot1.right + mDotSpacing, handleTop,
dot1.right + mDotSpacing + mDotSize, handleBottom
);
RectF dot3 = new RectF(
dot2.right + mDotSpacing, handleTop,
dot2.right + mDotSpacing + mDotSize, handleBottom
);
mPath.reset();
mPath.addOval(dot1, Path.Direction.CW);
mPath.addOval(dot2, Path.Direction.CW);
mPath.addOval(dot3, Path.Direction.CW);
outline.setPath(mPath);
} }
}); });
} }

View File

@@ -24,6 +24,7 @@ import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Region; import android.graphics.Region;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.view.TouchDelegate;
import android.view.View; import android.view.View;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.widget.FrameLayout; import android.widget.FrameLayout;
@@ -68,6 +69,10 @@ public class BubbleBarLayerView extends FrameLayout
private final Region mTouchableRegion = new Region(); private final Region mTouchableRegion = new Region();
private final Rect mTempRect = new Rect(); private final Rect mTempRect = new Rect();
// Used to ensure touch target size for the menu shown on a bubble expanded view
private TouchDelegate mHandleTouchDelegate;
private final Rect mHandleTouchBounds = new Rect();
public BubbleBarLayerView(Context context, BubbleController controller) { public BubbleBarLayerView(Context context, BubbleController controller) {
super(context); super(context);
mBubbleController = controller; mBubbleController = controller;
@@ -164,7 +169,17 @@ public class BubbleBarLayerView extends FrameLayout
mIsExpanded = true; mIsExpanded = true;
mBubbleController.getSysuiProxy().onStackExpandChanged(true); mBubbleController.getSysuiProxy().onStackExpandChanged(true);
mAnimationHelper.animateExpansion(mExpandedBubble); mAnimationHelper.animateExpansion(mExpandedBubble, () -> {
if (mExpandedView == null) return;
// Touch delegate for the menu
BubbleBarHandleView view = mExpandedView.getHandleView();
view.getBoundsOnScreen(mHandleTouchBounds);
mHandleTouchBounds.top -= mPositioner.getBubblePaddingTop();
mHandleTouchDelegate = new TouchDelegate(mHandleTouchBounds,
mExpandedView.getHandleView());
setTouchDelegate(mHandleTouchDelegate);
});
showScrim(true); showScrim(true);
} }
@@ -175,6 +190,7 @@ public class BubbleBarLayerView extends FrameLayout
mAnimationHelper.animateCollapse(() -> removeView(viewToRemove)); mAnimationHelper.animateCollapse(() -> removeView(viewToRemove));
mBubbleController.getSysuiProxy().onStackExpandChanged(false); mBubbleController.getSysuiProxy().onStackExpandChanged(false);
mExpandedView = null; mExpandedView = null;
setTouchDelegate(null);
showScrim(false); showScrim(false);
} }