Show the overflow expanded view in bubble bar
When the overflow bubble is selected in the bubble bar
we now show the expanded view for it. Rather than calculating
the Y for expanded views and align them with the top,
the positioner now calculates the bottom of the expanded view
so that we can align them above the bubble bar easily.
Fixes: 287121592
Fixes: 271468319
Test: - atest BubblesTest
- atest BubbleOverflowTest
- manual:
- Enalbe bubble bar
- Add a bubble
- Expand the overflow
- Expanded view should show the overflow state
Change-Id: I2db22a8e7878b5c644d72472e14848b0d36a62b3
This commit is contained in:
@@ -780,7 +780,7 @@ public class BubbleController implements ConfigurationChangeListener,
|
||||
try {
|
||||
mAddedToWindowManager = true;
|
||||
registerBroadcastReceiver();
|
||||
mBubbleData.getOverflow().initialize(this);
|
||||
mBubbleData.getOverflow().initialize(this, isShowingAsBubbleBar());
|
||||
// (TODO: b/273314541) some duplication in the inset listener
|
||||
if (isShowingAsBubbleBar()) {
|
||||
mWindowManager.addView(mLayerView, mWmLayoutParams);
|
||||
@@ -1077,6 +1077,13 @@ public class BubbleController implements ConfigurationChangeListener,
|
||||
@VisibleForTesting
|
||||
public void expandStackAndSelectBubbleFromLauncher(String key, boolean onLauncherHome) {
|
||||
mBubblePositioner.setShowingInBubbleBar(onLauncherHome);
|
||||
|
||||
if (BubbleOverflow.KEY.equals(key)) {
|
||||
mBubbleData.setSelectedBubbleFromLauncher(mBubbleData.getOverflow());
|
||||
mLayerView.showExpandedView(mBubbleData.getOverflow());
|
||||
return;
|
||||
}
|
||||
|
||||
Bubble b = mBubbleData.getAnyBubbleWithkey(key);
|
||||
if (b == null) {
|
||||
return;
|
||||
|
||||
@@ -948,9 +948,9 @@ public class BubbleExpandedView extends LinearLayout {
|
||||
mTaskView.onLocationChanged();
|
||||
}
|
||||
if (mIsOverflow) {
|
||||
post(() -> {
|
||||
mOverflowView.show();
|
||||
});
|
||||
// post this to the looper so that the view has a chance to be laid out before it can
|
||||
// calculate row and column sizes correctly.
|
||||
post(() -> mOverflowView.show());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl
|
||||
|
||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
private var expandedView: BubbleExpandedView?
|
||||
private var bubbleBarExpandedView: BubbleBarExpandedView? = null
|
||||
private var overflowBtn: BadgedImageView?
|
||||
|
||||
init {
|
||||
@@ -53,19 +54,26 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl
|
||||
}
|
||||
|
||||
/** Call before use and again if cleanUpExpandedState was called. */
|
||||
fun initialize(controller: BubbleController) {
|
||||
createExpandedView()
|
||||
getExpandedView()?.initialize(controller, controller.stackView, true /* isOverflow */)
|
||||
fun initialize(controller: BubbleController, forBubbleBar: Boolean) {
|
||||
if (forBubbleBar) {
|
||||
createBubbleBarExpandedView().initialize(controller, true /* isOverflow */)
|
||||
} else {
|
||||
createExpandedView()
|
||||
.initialize(controller, controller.stackView, true /* isOverflow */)
|
||||
}
|
||||
}
|
||||
|
||||
fun cleanUpExpandedState() {
|
||||
expandedView?.cleanUpExpandedState()
|
||||
expandedView = null
|
||||
bubbleBarExpandedView?.cleanUpExpandedState()
|
||||
bubbleBarExpandedView = null
|
||||
}
|
||||
|
||||
fun update() {
|
||||
updateResources()
|
||||
getExpandedView()?.applyThemeAttrs()
|
||||
getBubbleBarExpandedView()?.applyThemeAttrs()
|
||||
// Apply inset and new style to fresh icon drawable.
|
||||
getIconView()?.setIconImageResource(R.drawable.bubble_ic_overflow_button)
|
||||
updateBtnTheme()
|
||||
@@ -151,26 +159,39 @@ class BubbleOverflow(private val context: Context, private val positioner: Bubbl
|
||||
overflowBtn?.updateDotVisibility(true /* animate */)
|
||||
}
|
||||
|
||||
fun createExpandedView(): BubbleExpandedView? {
|
||||
expandedView =
|
||||
/** Creates the expanded view for bubbles showing in the stack view. */
|
||||
private fun createExpandedView(): BubbleExpandedView {
|
||||
val view =
|
||||
inflater.inflate(
|
||||
R.layout.bubble_expanded_view,
|
||||
null /* root */,
|
||||
false /* attachToRoot */
|
||||
) as BubbleExpandedView
|
||||
expandedView?.applyThemeAttrs()
|
||||
view.applyThemeAttrs()
|
||||
expandedView = view
|
||||
updateResources()
|
||||
return expandedView
|
||||
return view
|
||||
}
|
||||
|
||||
override fun getExpandedView(): BubbleExpandedView? {
|
||||
return expandedView
|
||||
}
|
||||
|
||||
override fun getBubbleBarExpandedView(): BubbleBarExpandedView? {
|
||||
return null
|
||||
/** Creates the expanded view for bubbles showing in the bubble bar. */
|
||||
private fun createBubbleBarExpandedView(): BubbleBarExpandedView {
|
||||
val view =
|
||||
inflater.inflate(
|
||||
R.layout.bubble_bar_expanded_view,
|
||||
null, /* root */
|
||||
false /* attachToRoot*/
|
||||
) as BubbleBarExpandedView
|
||||
view.applyThemeAttrs()
|
||||
bubbleBarExpandedView = view
|
||||
return view
|
||||
}
|
||||
|
||||
override fun getBubbleBarExpandedView(): BubbleBarExpandedView? = bubbleBarExpandedView
|
||||
|
||||
override fun getDotColor(): Int {
|
||||
return dotColor
|
||||
}
|
||||
|
||||
@@ -732,17 +732,25 @@ public class BubblePositioner {
|
||||
/**
|
||||
* How wide the expanded view should be when showing from the bubble bar.
|
||||
*/
|
||||
public int getExpandedViewWidthForBubbleBar() {
|
||||
return mExpandedViewLargeScreenWidth;
|
||||
public int getExpandedViewWidthForBubbleBar(boolean isOverflow) {
|
||||
return isOverflow ? mOverflowWidth : mExpandedViewLargeScreenWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* How tall the expanded view should be when showing from the bubble bar.
|
||||
*/
|
||||
public int getExpandedViewHeightForBubbleBar() {
|
||||
public int getExpandedViewHeightForBubbleBar(boolean isOverflow) {
|
||||
return isOverflow
|
||||
? mOverflowHeight
|
||||
: getExpandedViewBottomForBubbleBar() - mInsets.top - mExpandedViewPadding;
|
||||
}
|
||||
|
||||
/** The bottom position of the expanded view when showing above the bubble bar. */
|
||||
public int getExpandedViewBottomForBubbleBar() {
|
||||
return getAvailableRect().height()
|
||||
+ mInsets.top
|
||||
- mBubbleBarSize
|
||||
- mExpandedViewPadding * 2
|
||||
- mExpandedViewPadding
|
||||
- getBubbleBarHomeAdjustment();
|
||||
}
|
||||
|
||||
|
||||
@@ -1500,9 +1500,6 @@ public class BubbleStackView extends FrameLayout
|
||||
getViewTreeObserver().removeOnPreDrawListener(mViewUpdater);
|
||||
getViewTreeObserver().removeOnDrawListener(mSystemGestureExcludeUpdater);
|
||||
getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
|
||||
if (mBubbleOverflow != null) {
|
||||
mBubbleOverflow.cleanUpExpandedState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -176,44 +176,14 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
||||
LayoutInflater inflater = LayoutInflater.from(c);
|
||||
info.bubbleBarExpandedView = (BubbleBarExpandedView) inflater.inflate(
|
||||
R.layout.bubble_bar_expanded_view, layerView, false /* attachToRoot */);
|
||||
info.bubbleBarExpandedView.initialize(controller);
|
||||
info.bubbleBarExpandedView.initialize(controller, false /* isOverflow */);
|
||||
}
|
||||
|
||||
if (b.getShortcutInfo() != null) {
|
||||
info.shortcutInfo = b.getShortcutInfo();
|
||||
}
|
||||
|
||||
// App name & app icon
|
||||
PackageManager pm = BubbleController.getPackageManagerForUser(c,
|
||||
b.getUser().getIdentifier());
|
||||
ApplicationInfo appInfo;
|
||||
Drawable badgedIcon;
|
||||
Drawable appIcon;
|
||||
try {
|
||||
appInfo = pm.getApplicationInfo(
|
||||
b.getPackageName(),
|
||||
PackageManager.MATCH_UNINSTALLED_PACKAGES
|
||||
| PackageManager.MATCH_DISABLED_COMPONENTS
|
||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
|
||||
| PackageManager.MATCH_DIRECT_BOOT_AWARE);
|
||||
if (appInfo != null) {
|
||||
info.appName = String.valueOf(pm.getApplicationLabel(appInfo));
|
||||
}
|
||||
appIcon = pm.getApplicationIcon(b.getPackageName());
|
||||
badgedIcon = pm.getUserBadgedIcon(appIcon, b.getUser());
|
||||
} catch (PackageManager.NameNotFoundException exception) {
|
||||
// If we can't find package... don't think we should show the bubble.
|
||||
Log.w(TAG, "Unable to find package: " + b.getPackageName());
|
||||
if (!populateCommonInfo(info, c, b, iconFactory)) {
|
||||
// if we failed to update common fields return null
|
||||
return null;
|
||||
}
|
||||
|
||||
info.rawBadgeBitmap = iconFactory.getBadgeBitmap(badgedIcon, false).icon;
|
||||
float[] bubbleBitmapScale = new float[1];
|
||||
info.bubbleBitmap = iconFactory.getBubbleBitmap(
|
||||
iconFactory.getBubbleDrawable(c, info.shortcutInfo,
|
||||
b.getIcon()), bubbleBitmapScale);
|
||||
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -236,66 +206,11 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
||||
info.expandedView.initialize(controller, stackView, false /* isOverflow */);
|
||||
}
|
||||
|
||||
if (b.getShortcutInfo() != null) {
|
||||
info.shortcutInfo = b.getShortcutInfo();
|
||||
}
|
||||
|
||||
// App name & app icon
|
||||
PackageManager pm = BubbleController.getPackageManagerForUser(c,
|
||||
b.getUser().getIdentifier());
|
||||
ApplicationInfo appInfo;
|
||||
Drawable badgedIcon;
|
||||
Drawable appIcon;
|
||||
try {
|
||||
appInfo = pm.getApplicationInfo(
|
||||
b.getPackageName(),
|
||||
PackageManager.MATCH_UNINSTALLED_PACKAGES
|
||||
| PackageManager.MATCH_DISABLED_COMPONENTS
|
||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
|
||||
| PackageManager.MATCH_DIRECT_BOOT_AWARE);
|
||||
if (appInfo != null) {
|
||||
info.appName = String.valueOf(pm.getApplicationLabel(appInfo));
|
||||
}
|
||||
appIcon = pm.getApplicationIcon(b.getPackageName());
|
||||
badgedIcon = pm.getUserBadgedIcon(appIcon, b.getUser());
|
||||
} catch (PackageManager.NameNotFoundException exception) {
|
||||
// If we can't find package... don't think we should show the bubble.
|
||||
Log.w(TAG, "Unable to find package: " + b.getPackageName());
|
||||
if (!populateCommonInfo(info, c, b, iconFactory)) {
|
||||
// if we failed to update common fields return null
|
||||
return null;
|
||||
}
|
||||
|
||||
// Badged bubble image
|
||||
Drawable bubbleDrawable = iconFactory.getBubbleDrawable(c, info.shortcutInfo,
|
||||
b.getIcon());
|
||||
if (bubbleDrawable == null) {
|
||||
// Default to app icon
|
||||
bubbleDrawable = appIcon;
|
||||
}
|
||||
|
||||
BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon,
|
||||
b.isImportantConversation());
|
||||
info.badgeBitmap = badgeBitmapInfo.icon;
|
||||
// Raw badge bitmap never includes the important conversation ring
|
||||
info.rawBadgeBitmap = b.isImportantConversation()
|
||||
? iconFactory.getBadgeBitmap(badgedIcon, false).icon
|
||||
: badgeBitmapInfo.icon;
|
||||
|
||||
float[] bubbleBitmapScale = new float[1];
|
||||
info.bubbleBitmap = iconFactory.getBubbleBitmap(bubbleDrawable, bubbleBitmapScale);
|
||||
|
||||
// Dot color & placement
|
||||
Path iconPath = PathParser.createPathFromPathData(
|
||||
c.getResources().getString(com.android.internal.R.string.config_icon_mask));
|
||||
Matrix matrix = new Matrix();
|
||||
float scale = bubbleBitmapScale[0];
|
||||
float radius = DEFAULT_PATH_SIZE / 2f;
|
||||
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
|
||||
radius /* pivot y */);
|
||||
iconPath.transform(matrix);
|
||||
info.dotPath = iconPath;
|
||||
info.dotColor = ColorUtils.blendARGB(badgeBitmapInfo.color,
|
||||
Color.WHITE, WHITE_SCRIM_ALPHA);
|
||||
|
||||
// Flyout
|
||||
info.flyoutMessage = b.getFlyoutMessage();
|
||||
if (info.flyoutMessage != null) {
|
||||
@@ -306,6 +221,75 @@ public class BubbleViewInfoTask extends AsyncTask<Void, Void, BubbleViewInfoTask
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies the given {@code info} object and populates common fields in it.
|
||||
*
|
||||
* <p>This method returns {@code true} if the update was successful and {@code false} otherwise.
|
||||
* Callers should assume that the info object is unusable if the update was unsuccessful.
|
||||
*/
|
||||
private static boolean populateCommonInfo(
|
||||
BubbleViewInfo info, Context c, Bubble b, BubbleIconFactory iconFactory) {
|
||||
if (b.getShortcutInfo() != null) {
|
||||
info.shortcutInfo = b.getShortcutInfo();
|
||||
}
|
||||
|
||||
// App name & app icon
|
||||
PackageManager pm = BubbleController.getPackageManagerForUser(c,
|
||||
b.getUser().getIdentifier());
|
||||
ApplicationInfo appInfo;
|
||||
Drawable badgedIcon;
|
||||
Drawable appIcon;
|
||||
try {
|
||||
appInfo = pm.getApplicationInfo(
|
||||
b.getPackageName(),
|
||||
PackageManager.MATCH_UNINSTALLED_PACKAGES
|
||||
| PackageManager.MATCH_DISABLED_COMPONENTS
|
||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE
|
||||
| PackageManager.MATCH_DIRECT_BOOT_AWARE);
|
||||
if (appInfo != null) {
|
||||
info.appName = String.valueOf(pm.getApplicationLabel(appInfo));
|
||||
}
|
||||
appIcon = pm.getApplicationIcon(b.getPackageName());
|
||||
badgedIcon = pm.getUserBadgedIcon(appIcon, b.getUser());
|
||||
} catch (PackageManager.NameNotFoundException exception) {
|
||||
// If we can't find package... don't think we should show the bubble.
|
||||
Log.w(TAG, "Unable to find package: " + b.getPackageName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Badged bubble image
|
||||
Drawable bubbleDrawable = iconFactory.getBubbleDrawable(c, info.shortcutInfo, b.getIcon());
|
||||
if (bubbleDrawable == null) {
|
||||
// Default to app icon
|
||||
bubbleDrawable = appIcon;
|
||||
}
|
||||
|
||||
BitmapInfo badgeBitmapInfo = iconFactory.getBadgeBitmap(badgedIcon,
|
||||
b.isImportantConversation());
|
||||
info.badgeBitmap = badgeBitmapInfo.icon;
|
||||
// Raw badge bitmap never includes the important conversation ring
|
||||
info.rawBadgeBitmap = b.isImportantConversation() // is this needed for bar?
|
||||
? iconFactory.getBadgeBitmap(badgedIcon, false).icon
|
||||
: badgeBitmapInfo.icon;
|
||||
|
||||
float[] bubbleBitmapScale = new float[1];
|
||||
info.bubbleBitmap = iconFactory.getBubbleBitmap(bubbleDrawable, bubbleBitmapScale);
|
||||
|
||||
// Dot color & placement
|
||||
Path iconPath = PathParser.createPathFromPathData(
|
||||
c.getResources().getString(com.android.internal.R.string.config_icon_mask));
|
||||
Matrix matrix = new Matrix();
|
||||
float scale = bubbleBitmapScale[0];
|
||||
float radius = DEFAULT_PATH_SIZE / 2f;
|
||||
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
|
||||
radius /* pivot y */);
|
||||
iconPath.transform(matrix);
|
||||
info.dotPath = iconPath;
|
||||
info.dotColor = ColorUtils.blendARGB(badgeBitmapInfo.color,
|
||||
Color.WHITE, WHITE_SCRIM_ALPHA);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static Drawable loadSenderAvatar(@NonNull final Context context, @Nullable final Icon icon) {
|
||||
Objects.requireNonNull(context);
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.widget.FrameLayout;
|
||||
|
||||
import com.android.wm.shell.animation.Interpolators;
|
||||
import com.android.wm.shell.animation.PhysicsAnimator;
|
||||
import com.android.wm.shell.bubbles.BubbleOverflow;
|
||||
import com.android.wm.shell.bubbles.BubblePositioner;
|
||||
import com.android.wm.shell.bubbles.BubbleViewProvider;
|
||||
import com.android.wm.shell.bubbles.animation.AnimatableScaleMatrix;
|
||||
@@ -215,9 +216,10 @@ public class BubbleBarAnimationHelper {
|
||||
}
|
||||
BubbleBarExpandedView bbev = mExpandedBubble.getBubbleBarExpandedView();
|
||||
|
||||
boolean isOverflowExpanded = mExpandedBubble.getKey().equals(BubbleOverflow.KEY);
|
||||
final int padding = mPositioner.getBubbleBarExpandedViewPadding();
|
||||
final int width = mPositioner.getExpandedViewWidthForBubbleBar();
|
||||
final int height = mPositioner.getExpandedViewHeightForBubbleBar();
|
||||
final int width = mPositioner.getExpandedViewWidthForBubbleBar(isOverflowExpanded);
|
||||
final int height = mPositioner.getExpandedViewHeightForBubbleBar(isOverflowExpanded);
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) bbev.getLayoutParams();
|
||||
lp.width = width;
|
||||
lp.height = height;
|
||||
@@ -227,7 +229,8 @@ public class BubbleBarAnimationHelper {
|
||||
} else {
|
||||
bbev.setX(mPositioner.getAvailableRect().width() - width - padding);
|
||||
}
|
||||
bbev.setY(mPositioner.getInsets().top + padding);
|
||||
bbev.setY(mPositioner.getExpandedViewBottomForBubbleBar() - height);
|
||||
bbev.updateLocation();
|
||||
bbev.maybeShowOverflow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.graphics.Color;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.widget.FrameLayout;
|
||||
@@ -33,6 +34,7 @@ import com.android.internal.policy.ScreenDecorationsUtils;
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.bubbles.Bubble;
|
||||
import com.android.wm.shell.bubbles.BubbleController;
|
||||
import com.android.wm.shell.bubbles.BubbleOverflowContainerView;
|
||||
import com.android.wm.shell.bubbles.BubbleTaskViewHelper;
|
||||
import com.android.wm.shell.bubbles.Bubbles;
|
||||
import com.android.wm.shell.taskview.TaskView;
|
||||
@@ -51,6 +53,7 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
|
||||
private static final int INVALID_TASK_ID = -1;
|
||||
|
||||
private BubbleController mController;
|
||||
private boolean mIsOverflow;
|
||||
private BubbleTaskViewHelper mBubbleTaskViewHelper;
|
||||
private BubbleBarMenuViewController mMenuViewController;
|
||||
private @Nullable Supplier<Rect> mLayerBoundsSupplier;
|
||||
@@ -58,6 +61,7 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
|
||||
|
||||
private BubbleBarHandleView mHandleView = new BubbleBarHandleView(getContext());
|
||||
private @Nullable TaskView mTaskView;
|
||||
private @Nullable BubbleOverflowContainerView mOverflowView;
|
||||
|
||||
private int mHandleHeight;
|
||||
private int mBackgroundColor;
|
||||
@@ -114,15 +118,25 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
|
||||
}
|
||||
|
||||
/** Set the BubbleController on the view, must be called before doing anything else. */
|
||||
public void initialize(BubbleController controller) {
|
||||
public void initialize(BubbleController controller, boolean isOverflow) {
|
||||
mController = controller;
|
||||
mBubbleTaskViewHelper = new BubbleTaskViewHelper(mContext, mController,
|
||||
/* listener= */ this,
|
||||
/* viewParent= */ this);
|
||||
mTaskView = mBubbleTaskViewHelper.getTaskView();
|
||||
addView(mTaskView);
|
||||
mTaskView.setEnableSurfaceClipping(true);
|
||||
mTaskView.setCornerRadius(mCornerRadius);
|
||||
mIsOverflow = isOverflow;
|
||||
|
||||
if (mIsOverflow) {
|
||||
mOverflowView = (BubbleOverflowContainerView) LayoutInflater.from(getContext()).inflate(
|
||||
R.layout.bubble_overflow_container, null /* root */);
|
||||
mOverflowView.setBubbleController(mController);
|
||||
addView(mOverflowView);
|
||||
} else {
|
||||
|
||||
mBubbleTaskViewHelper = new BubbleTaskViewHelper(mContext, mController,
|
||||
/* listener= */ this,
|
||||
/* viewParent= */ this);
|
||||
mTaskView = mBubbleTaskViewHelper.getTaskView();
|
||||
addView(mTaskView);
|
||||
mTaskView.setEnableSurfaceClipping(true);
|
||||
mTaskView.setCornerRadius(mCornerRadius);
|
||||
}
|
||||
mMenuViewController = new BubbleBarMenuViewController(mContext, this);
|
||||
mMenuViewController.setListener(new BubbleBarMenuViewController.Listener() {
|
||||
@Override
|
||||
@@ -156,7 +170,8 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
|
||||
}
|
||||
|
||||
// TODO (b/275087636): call this when theme/config changes
|
||||
void applyThemeAttrs() {
|
||||
/** Updates the view based on the current theme. */
|
||||
public void applyThemeAttrs() {
|
||||
boolean supportsRoundedCorners = ScreenDecorationsUtils.supportsRoundedCornersOnWindows(
|
||||
mContext.getResources());
|
||||
final TypedArray ta = mContext.obtainStyledAttributes(new int[]{
|
||||
@@ -257,8 +272,18 @@ public class BubbleBarExpandedView extends FrameLayout implements BubbleTaskView
|
||||
* Call when the location or size of the view has changed to update TaskView.
|
||||
*/
|
||||
public void updateLocation() {
|
||||
if (mTaskView == null) return;
|
||||
mTaskView.onLocationChanged();
|
||||
if (mTaskView != null) {
|
||||
mTaskView.onLocationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/** Shows the expanded view for the overflow if it exists. */
|
||||
void maybeShowOverflow() {
|
||||
if (mOverflowView != null) {
|
||||
// post this to the looper so that the view has a chance to be laid out before it can
|
||||
// calculate row and column sizes correctly.
|
||||
post(() -> mOverflowView.show());
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the alpha of the task view. */
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.view.ViewTreeObserver;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.wm.shell.bubbles.BubbleController;
|
||||
import com.android.wm.shell.bubbles.BubbleOverflow;
|
||||
import com.android.wm.shell.bubbles.BubblePositioner;
|
||||
import com.android.wm.shell.bubbles.BubbleViewProvider;
|
||||
|
||||
@@ -146,8 +147,9 @@ public class BubbleBarLayerView extends FrameLayout
|
||||
if (mExpandedView == null) {
|
||||
mExpandedBubble = b;
|
||||
mExpandedView = expandedView;
|
||||
final int width = mPositioner.getExpandedViewWidthForBubbleBar();
|
||||
final int height = mPositioner.getExpandedViewHeightForBubbleBar();
|
||||
boolean isOverflowExpanded = b.getKey().equals(BubbleOverflow.KEY);
|
||||
final int width = mPositioner.getExpandedViewWidthForBubbleBar(isOverflowExpanded);
|
||||
final int height = mPositioner.getExpandedViewHeightForBubbleBar(isOverflowExpanded);
|
||||
mExpandedView.setVisibility(GONE);
|
||||
mExpandedView.setUnBubbleConversationCallback(mUnBubbleConversationCallback);
|
||||
mExpandedView.setLayerBoundsSupplier(() -> new Rect(0, 0, getWidth(), getHeight()));
|
||||
@@ -156,6 +158,7 @@ public class BubbleBarLayerView extends FrameLayout
|
||||
mUnBubbleConversationCallback.accept(bubbleKey);
|
||||
}
|
||||
});
|
||||
mExpandedView.setY(mPositioner.getExpandedViewBottomForBubbleBar() - height);
|
||||
addView(mExpandedView, new FrameLayout.LayoutParams(width, height));
|
||||
}
|
||||
|
||||
@@ -184,9 +187,10 @@ public class BubbleBarLayerView extends FrameLayout
|
||||
/** Updates the expanded view size and position. */
|
||||
private void updateExpandedView() {
|
||||
if (mExpandedView == null) return;
|
||||
boolean isOverflowExpanded = mExpandedBubble.getKey().equals(BubbleOverflow.KEY);
|
||||
final int padding = mPositioner.getBubbleBarExpandedViewPadding();
|
||||
final int width = mPositioner.getExpandedViewWidthForBubbleBar();
|
||||
final int height = mPositioner.getExpandedViewHeightForBubbleBar();
|
||||
final int width = mPositioner.getExpandedViewWidthForBubbleBar(isOverflowExpanded);
|
||||
final int height = mPositioner.getExpandedViewHeightForBubbleBar(isOverflowExpanded);
|
||||
FrameLayout.LayoutParams lp = (LayoutParams) mExpandedView.getLayoutParams();
|
||||
lp.width = width;
|
||||
lp.height = height;
|
||||
@@ -196,7 +200,7 @@ public class BubbleBarLayerView extends FrameLayout
|
||||
} else {
|
||||
mExpandedView.setX(mPositioner.getAvailableRect().width() - width - padding);
|
||||
}
|
||||
mExpandedView.setY(mPositioner.getInsets().top + padding);
|
||||
mExpandedView.setY(mPositioner.getExpandedViewBottomForBubbleBar() - height);
|
||||
mExpandedView.updateLocation();
|
||||
}
|
||||
|
||||
|
||||
@@ -64,18 +64,27 @@ public class BubbleOverflowTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_initialize() {
|
||||
public void test_initialize_forStack() {
|
||||
assertThat(mOverflow.getExpandedView()).isNull();
|
||||
|
||||
mOverflow.initialize(mBubbleController);
|
||||
mOverflow.initialize(mBubbleController, /* forBubbleBar= */ false);
|
||||
|
||||
assertThat(mOverflow.getExpandedView()).isNotNull();
|
||||
assertThat(mOverflow.getExpandedView().getBubbleKey()).isEqualTo(BubbleOverflow.KEY);
|
||||
assertThat(mOverflow.getBubbleBarExpandedView()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_initialize_forBubbleBar() {
|
||||
mOverflow.initialize(mBubbleController, /* forBubbleBar= */ true);
|
||||
|
||||
assertThat(mOverflow.getBubbleBarExpandedView()).isNotNull();
|
||||
assertThat(mOverflow.getExpandedView()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_cleanUpExpandedState() {
|
||||
mOverflow.createExpandedView();
|
||||
mOverflow.initialize(mBubbleController, /* forBubbleBar= */ false);
|
||||
assertThat(mOverflow.getExpandedView()).isNotNull();
|
||||
|
||||
mOverflow.cleanUpExpandedState();
|
||||
|
||||
@@ -133,8 +133,10 @@ import com.android.wm.shell.bubbles.BubbleData;
|
||||
import com.android.wm.shell.bubbles.BubbleDataRepository;
|
||||
import com.android.wm.shell.bubbles.BubbleEntry;
|
||||
import com.android.wm.shell.bubbles.BubbleLogger;
|
||||
import com.android.wm.shell.bubbles.BubbleOverflow;
|
||||
import com.android.wm.shell.bubbles.BubbleStackView;
|
||||
import com.android.wm.shell.bubbles.BubbleViewInfoTask;
|
||||
import com.android.wm.shell.bubbles.BubbleViewProvider;
|
||||
import com.android.wm.shell.bubbles.Bubbles;
|
||||
import com.android.wm.shell.bubbles.StackEducationViewKt;
|
||||
import com.android.wm.shell.bubbles.properties.BubbleProperties;
|
||||
@@ -1936,6 +1938,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
assertThat(mBubbleData.getBubbles()).hasSize(1);
|
||||
assertBubbleIsInflatedForStack(mBubbleData.getBubbles().get(0));
|
||||
assertBubbleIsInflatedForStack(mBubbleData.getOverflow());
|
||||
|
||||
FakeBubbleStateListener bubbleStateListener = new FakeBubbleStateListener();
|
||||
mBubbleController.registerBubbleStateListener(bubbleStateListener);
|
||||
@@ -1944,6 +1947,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
assertThat(mBubbleData.getBubbles()).hasSize(1);
|
||||
assertBubbleIsInflatedForBar(mBubbleData.getBubbles().get(0));
|
||||
assertBubbleIsInflatedForBar(mBubbleData.getOverflow());
|
||||
|
||||
mBubbleController.unregisterBubbleStateListener();
|
||||
|
||||
@@ -1951,6 +1955,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
|
||||
assertThat(mBubbleData.getBubbles()).hasSize(1);
|
||||
assertBubbleIsInflatedForStack(mBubbleData.getBubbles().get(0));
|
||||
assertBubbleIsInflatedForStack(mBubbleData.getOverflow());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2118,7 +2123,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
/** Asserts that the given bubble has the stack expanded view inflated. */
|
||||
private void assertBubbleIsInflatedForStack(Bubble b) {
|
||||
private void assertBubbleIsInflatedForStack(BubbleViewProvider b) {
|
||||
assertThat(b.getIconView()).isNotNull();
|
||||
assertThat(b.getExpandedView()).isNotNull();
|
||||
assertThat(b.getBubbleBarExpandedView()).isNull();
|
||||
@@ -2131,8 +2136,14 @@ public class BubblesTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
/** Asserts that the given bubble has the bar expanded view inflated. */
|
||||
private void assertBubbleIsInflatedForBar(Bubble b) {
|
||||
assertThat(b.getIconView()).isNull();
|
||||
private void assertBubbleIsInflatedForBar(BubbleViewProvider b) {
|
||||
// the icon view should be inflated for the overflow but not for other bubbles when showing
|
||||
// in the bar
|
||||
if (b instanceof Bubble) {
|
||||
assertThat(b.getIconView()).isNull();
|
||||
} else if (b instanceof BubbleOverflow) {
|
||||
assertThat(b.getIconView()).isNotNull();
|
||||
}
|
||||
assertThat(b.getExpandedView()).isNull();
|
||||
assertThat(b.getBubbleBarExpandedView()).isNotNull();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user