mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 23:36:47 +00:00
Merge "Adds an overflow bubble to the bubble bar." into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
936722a71f
@@ -363,6 +363,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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -101,7 +101,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");
|
||||
}
|
||||
@@ -236,7 +236,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 {
|
||||
@@ -247,7 +247,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);
|
||||
@@ -268,7 +268,7 @@ public class BubbleBarViewController {
|
||||
/**
|
||||
* Updates the selected bubble.
|
||||
*/
|
||||
public void updateSelectedBubble(BubbleBarBubble newlySelected) {
|
||||
public void updateSelectedBubble(BubbleBarItem newlySelected) {
|
||||
mBarView.setSelectedBubble(newlySelected.getView());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
24
res/drawable/bubble_ic_overflow_button.xml
Normal file
24
res/drawable/bubble_ic_overflow_button.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright (C) 2023 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:width="24dp"
|
||||
android:height="24dp">
|
||||
<path
|
||||
android:fillColor="#1A73E8"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||
</vector>
|
||||
Reference in New Issue
Block a user