Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f78d55ba authored by Liran Binyamin's avatar Liran Binyamin
Browse files

Adds an overflow bubble to the bubble bar.

Bug: 271468319
Test: Tested on a physical device
Change-Id: Ib4ad62779173ab8010e5e5d25bf5415fee1b1d41
parent 52fbedf2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -360,6 +360,7 @@
    <dimen name="bubblebar_icon_size">50dp</dimen>
    <dimen name="bubblebar_badge_size">24dp</dimen>
    <dimen name="bubblebar_icon_overlap">12dp</dimen>
    <dimen name="bubblebar_overflow_inset">24dp</dimen>
    <dimen name="bubblebar_icon_spacing">3dp</dimen>
    <dimen name="bubblebar_icon_elevation">1dp</dimen>

+52 −3
Original line number Diff line number Diff line
@@ -38,11 +38,15 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.os.Bundle;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -51,6 +55,8 @@ import android.util.Log;
import android.util.PathParser;
import android.view.LayoutInflater;

import androidx.appcompat.content.res.AppCompatResources;

import com.android.internal.graphics.ColorUtils;
import com.android.launcher3.R;
import com.android.launcher3.icons.BitmapInfo;
@@ -113,7 +119,8 @@ public class BubbleBarController extends IBubblesListener.Stub {
    private final LauncherApps mLauncherApps;
    private final BubbleIconFactory mIconFactory;

    private BubbleBarBubble mSelectedBubble;
    private BubbleBarItem mSelectedBubble;
    private BubbleBarOverflow mOverflowBubble;

    private BubbleBarViewController mBubbleBarViewController;
    private BubbleStashController mBubbleStashController;
@@ -178,6 +185,16 @@ public class BubbleBarController extends IBubblesListener.Stub {
            mBubbleBarViewController.setHiddenForBubbles(!BUBBLE_BAR_ENABLED);
            mBubbleStashedHandleViewController.setHiddenForBubbles(!BUBBLE_BAR_ENABLED);
        });

        BUBBLE_STATE_EXECUTOR.execute(() -> {
            if (mOverflowBubble == null) {
                BubbleBarOverflow overflow = createOverflow(mContext);
                mMainExecutor.execute(() -> {
                    mBubbleBarViewController.addBubble(overflow);
                    mOverflowBubble = overflow;
                });
            }
        });
    }

    /**
@@ -329,7 +346,7 @@ public class BubbleBarController extends IBubblesListener.Stub {
     * WMShell that the selection has changed, that should go through
     * {@link SystemUiProxy#showBubble}.
     */
    public void setSelectedBubble(BubbleBarBubble b) {
    public void setSelectedBubble(BubbleBarItem b) {
        if (!Objects.equals(b, mSelectedBubble)) {
            if (DEBUG) Log.w(TAG, "selectingBubble: " + b.getKey());
            mSelectedBubble = b;
@@ -424,7 +441,6 @@ public class BubbleBarController extends IBubblesListener.Stub {
        dotColor = ColorUtils.blendARGB(badgeBitmapInfo.color,
                Color.WHITE, WHITE_SCRIM_ALPHA);


        LayoutInflater inflater = LayoutInflater.from(context);
        BubbleView bubbleView = (BubbleView) inflater.inflate(
                R.layout.bubblebar_item_view, bbv, false /* attachToRoot */);
@@ -434,4 +450,37 @@ public class BubbleBarController extends IBubblesListener.Stub {
        bubbleView.setBubble(bubble);
        return bubble;
    }

    private BubbleBarOverflow createOverflow(Context context) {
        Bitmap bitmap = createOverflowBitmap(context);
        LayoutInflater inflater = LayoutInflater.from(context);
        BubbleView bubbleView = (BubbleView) inflater.inflate(
                R.layout.bubblebar_item_view, mBarView, false /* attachToRoot */);
        BubbleBarOverflow overflow = new BubbleBarOverflow(bubbleView);
        bubbleView.setOverflow(overflow, bitmap);
        return overflow;
    }

    private Bitmap createOverflowBitmap(Context context) {
        Drawable iconDrawable = AppCompatResources.getDrawable(mContext,
                R.drawable.bubble_ic_overflow_button);

        final TypedArray ta = mContext.obtainStyledAttributes(
                new int[]{
                        com.android.internal.R.attr.materialColorOnPrimaryFixed,
                        com.android.internal.R.attr.materialColorPrimaryFixed
                });
        int overflowIconColor = ta.getColor(0, Color.WHITE);
        int overflowBackgroundColor = ta.getColor(1, Color.BLACK);
        ta.recycle();

        iconDrawable.setTint(overflowIconColor);

        int inset = context.getResources().getDimensionPixelSize(R.dimen.bubblebar_overflow_inset);
        Drawable foreground = new InsetDrawable(iconDrawable, inset);
        Drawable drawable = new AdaptiveIconDrawable(new ColorDrawable(overflowBackgroundColor),
                foreground);

        return mIconFactory.createBadgedIconBitmap(drawable).icon;
    }
}
+7 −4
Original line number Diff line number Diff line
@@ -19,16 +19,19 @@ import android.graphics.Bitmap
import android.graphics.Path
import com.android.wm.shell.common.bubbles.BubbleInfo

/** An entity in the bubble bar. */
sealed class BubbleBarItem(open val key: String, open val view: BubbleView)

/** Contains state info about a bubble in the bubble bar as well as presentation information. */
data class BubbleBarBubble(
    val info: BubbleInfo,
    val view: BubbleView,
    override val view: BubbleView,
    val badge: Bitmap,
    val icon: Bitmap,
    val dotColor: Int,
    val dotPath: Path,
    val appName: String
) {
) : BubbleBarItem(info.key, view)

    val key: String = info.key
}
/** Represents the overflow bubble in the bubble bar. */
data class BubbleBarOverflow(override val view: BubbleView) : BubbleBarItem("overflow", view)
+4 −4
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ public class BubbleBarViewController {
    }

    private void onBubbleClicked(View v) {
        BubbleBarBubble bubble = ((BubbleView) v).getBubble();
        BubbleBarItem bubble = ((BubbleView) v).getBubble();
        if (bubble == null) {
            Log.e(TAG, "bubble click listener, bubble was null");
        }
@@ -228,7 +228,7 @@ public class BubbleBarViewController {
    /**
     * Removes the provided bubble from the bubble bar.
     */
    public void removeBubble(BubbleBarBubble b) {
    public void removeBubble(BubbleBarItem b) {
        if (b != null) {
            mBarView.removeView(b.getView());
        } else {
@@ -239,7 +239,7 @@ public class BubbleBarViewController {
    /**
     * Adds the provided bubble to the bubble bar.
     */
    public void addBubble(BubbleBarBubble b) {
    public void addBubble(BubbleBarItem b) {
        if (b != null) {
            mBarView.addView(b.getView(), 0, new FrameLayout.LayoutParams(mIconSize, mIconSize));
            b.getView().setOnClickListener(mBubbleClickListener);
@@ -260,7 +260,7 @@ public class BubbleBarViewController {
    /**
     * Updates the selected bubble.
     */
    public void updateSelectedBubble(BubbleBarBubble newlySelected) {
    public void updateSelectedBubble(BubbleBarItem newlySelected) {
        mBarView.setSelectedBubble(newlySelected.getView());
    }

+17 −4
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import com.android.launcher3.icons.IconNormalizer;

// TODO: (b/276978250) This is will be similar to WMShell's BadgedImageView, it'd be nice to share.
// TODO: (b/269670235) currently this doesn't show the 'update dot'

/**
 * View that displays a bubble icon, along with an app badge on either the left or
 * right side of the view.
@@ -48,7 +49,7 @@ public class BubbleView extends ConstraintLayout {
    // TODO: (b/273310265) handle RTL
    private boolean mOnLeft = false;

    private BubbleBarBubble mBubble;
    private BubbleBarItem mBubble;

    public BubbleView(Context context) {
        this(context, null);
@@ -97,15 +98,27 @@ public class BubbleView extends ConstraintLayout {
        mAppIcon.setImageBitmap(bubble.getBadge());
    }

    void setOverflow(BubbleBarOverflow overflow, Bitmap bitmap) {
        mBubble = overflow;
        mBubbleIcon.setImageBitmap(bitmap);
        hideBadge();
    }

    /** Returns the bubble being rendered in this view. */
    @Nullable
    BubbleBarBubble getBubble() {
    BubbleBarItem getBubble() {
        return mBubble;
    }

    /** Shows the app badge on this bubble. */
    void showBadge() {
        Bitmap appBadgeBitmap = mBubble.getBadge();
        if (mBubble instanceof BubbleBarOverflow) {
            // The overflow bubble does not have a badge, so just bail.
            return;
        }
        BubbleBarBubble bubble = (BubbleBarBubble) mBubble;

        Bitmap appBadgeBitmap = bubble.getBadge();
        if (appBadgeBitmap == null) {
            mAppIcon.setVisibility(GONE);
            return;
@@ -113,7 +126,7 @@ public class BubbleView extends ConstraintLayout {

        int translationX;
        if (mOnLeft) {
            translationX = -(mBubble.getIcon().getWidth() - appBadgeBitmap.getWidth());
            translationX = -(bubble.getIcon().getWidth() - appBadgeBitmap.getWidth());
        } else {
            translationX = 0;
        }
Loading