Merge "Inset the bubble bar expanded view instead of drawing our own header" into udc-qpr-dev
This commit is contained in:
@@ -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. -->
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user