Merge "Reorder overflow button with kotlin refactor"
This commit is contained in:
committed by
Android (Google) Code Review
commit
3ffe12b63a
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
package com.android.systemui.bubbles;
|
||||
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
import static android.view.View.GONE;
|
||||
|
||||
import static com.android.systemui.bubbles.BadgedImageView.DEFAULT_PATH_SIZE;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.drawable.AdaptiveIconDrawable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.InsetDrawable;
|
||||
import android.util.PathParser;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
/**
|
||||
* Class for showing aged out bubbles.
|
||||
*/
|
||||
public class BubbleOverflow implements BubbleViewProvider {
|
||||
public static final String KEY = "Overflow";
|
||||
|
||||
private BadgedImageView mOverflowBtn;
|
||||
private BubbleExpandedView mExpandedView;
|
||||
private LayoutInflater mInflater;
|
||||
private Context mContext;
|
||||
private Bitmap mIcon;
|
||||
private Path mPath;
|
||||
private int mBitmapSize;
|
||||
private int mIconBitmapSize;
|
||||
private int mDotColor;
|
||||
|
||||
public BubbleOverflow(Context context) {
|
||||
mContext = context;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
void setUpOverflow(ViewGroup parentViewGroup, BubbleStackView stackView) {
|
||||
updateDimensions();
|
||||
mExpandedView = (BubbleExpandedView) mInflater.inflate(
|
||||
R.layout.bubble_expanded_view, parentViewGroup /* root */,
|
||||
false /* attachToRoot */);
|
||||
mExpandedView.setOverflow(true);
|
||||
mExpandedView.setStackView(stackView);
|
||||
mExpandedView.applyThemeAttrs();
|
||||
updateIcon(mContext, parentViewGroup);
|
||||
}
|
||||
|
||||
void updateDimensions() {
|
||||
mBitmapSize = mContext.getResources().getDimensionPixelSize(R.dimen.bubble_bitmap_size);
|
||||
mIconBitmapSize = mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.bubble_overflow_icon_bitmap_size);
|
||||
if (mExpandedView != null) {
|
||||
mExpandedView.updateDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void updateIcon(Context context, ViewGroup parentViewGroup) {
|
||||
mContext = context;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mOverflowBtn = (BadgedImageView) mInflater.inflate(R.layout.bubble_overflow_button,
|
||||
parentViewGroup /* root */,
|
||||
false /* attachToRoot */);
|
||||
mOverflowBtn.setContentDescription(mContext.getResources().getString(
|
||||
R.string.bubble_overflow_button_content_description));
|
||||
Resources res = mContext.getResources();
|
||||
|
||||
// Set color for button icon and dot
|
||||
TypedValue typedValue = new TypedValue();
|
||||
mContext.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true);
|
||||
int colorAccent = mContext.getColor(typedValue.resourceId);
|
||||
mOverflowBtn.getDrawable().setTint(colorAccent);
|
||||
mDotColor = colorAccent;
|
||||
|
||||
// Set color for button and activity background
|
||||
ColorDrawable bg = new ColorDrawable(res.getColor(R.color.bubbles_light));
|
||||
final int mode = res.getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
if (mode == Configuration.UI_MODE_NIGHT_YES) {
|
||||
bg = new ColorDrawable(res.getColor(R.color.bubbles_dark));
|
||||
}
|
||||
|
||||
// Apply icon inset
|
||||
InsetDrawable fg = new InsetDrawable(mOverflowBtn.getDrawable(),
|
||||
mBitmapSize - mIconBitmapSize /* inset */);
|
||||
AdaptiveIconDrawable adaptiveIconDrawable = new AdaptiveIconDrawable(bg, fg);
|
||||
|
||||
BubbleIconFactory iconFactory = new BubbleIconFactory(mContext);
|
||||
mIcon = iconFactory.createBadgedIconBitmap(adaptiveIconDrawable,
|
||||
null /* user */,
|
||||
true /* shrinkNonAdaptiveIcons */).icon;
|
||||
|
||||
// Get path with dot location
|
||||
float scale = iconFactory.getNormalizer().getScale(mOverflowBtn.getDrawable(),
|
||||
null /* outBounds */, null /* path */, null /* outMaskShape */);
|
||||
float radius = DEFAULT_PATH_SIZE / 2f;
|
||||
mPath = PathParser.createPathFromPathData(
|
||||
mContext.getResources().getString(com.android.internal.R.string.config_icon_mask));
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
|
||||
radius /* pivot y */);
|
||||
mPath.transform(matrix);
|
||||
|
||||
mOverflowBtn.setRenderedBubble(this);
|
||||
}
|
||||
|
||||
void setVisible(int visible) {
|
||||
mOverflowBtn.setVisibility(visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BubbleExpandedView getExpandedView() {
|
||||
return mExpandedView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDotColor() {
|
||||
return mDotColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bitmap getBadgedImage() {
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showDot() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getDotPath() {
|
||||
return mPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentVisibility(boolean visible) {
|
||||
mExpandedView.setContentVisibility(visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getIconView() {
|
||||
return mOverflowBtn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKey() {
|
||||
return BubbleOverflow.KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDisplayId() {
|
||||
return mExpandedView != null ? mExpandedView.getVirtualDisplayId() : INVALID_DISPLAY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
package com.android.systemui.bubbles
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Matrix
|
||||
import android.graphics.Path
|
||||
import android.graphics.drawable.AdaptiveIconDrawable
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.InsetDrawable
|
||||
import android.util.PathParser
|
||||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import com.android.systemui.R
|
||||
|
||||
class BubbleOverflow(
|
||||
private val context: Context,
|
||||
private val stack: BubbleStackView
|
||||
) : BubbleViewProvider {
|
||||
|
||||
private var bitmap: Bitmap? = null
|
||||
private var dotPath: Path? = null
|
||||
private var bitmapSize = 0
|
||||
private var iconBitmapSize = 0
|
||||
private var dotColor = 0
|
||||
|
||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
private val expandedView: BubbleExpandedView = inflater
|
||||
.inflate(R.layout.bubble_expanded_view, null /* root */, false /* attachToRoot */)
|
||||
as BubbleExpandedView
|
||||
private val overflowBtn: BadgedImageView = inflater
|
||||
.inflate(R.layout.bubble_overflow_button, null /* root */, false /* attachToRoot */)
|
||||
as BadgedImageView
|
||||
init {
|
||||
updateResources()
|
||||
with(expandedView) {
|
||||
setOverflow(true)
|
||||
setStackView(stack)
|
||||
applyThemeAttrs()
|
||||
}
|
||||
with(overflowBtn) {
|
||||
setContentDescription(context.resources.getString(
|
||||
R.string.bubble_overflow_button_content_description))
|
||||
updateBtnTheme()
|
||||
}
|
||||
}
|
||||
|
||||
fun update() {
|
||||
updateResources()
|
||||
expandedView.applyThemeAttrs()
|
||||
// Apply inset and new style to fresh icon drawable.
|
||||
overflowBtn.setImageResource(R.drawable.ic_bubble_overflow_button)
|
||||
updateBtnTheme()
|
||||
}
|
||||
|
||||
fun updateResources() {
|
||||
bitmapSize = context.resources.getDimensionPixelSize(R.dimen.bubble_bitmap_size)
|
||||
iconBitmapSize = context.resources.getDimensionPixelSize(
|
||||
R.dimen.bubble_overflow_icon_bitmap_size)
|
||||
val bubbleSize = context.resources.getDimensionPixelSize(R.dimen.individual_bubble_size)
|
||||
overflowBtn.setLayoutParams(FrameLayout.LayoutParams(bubbleSize, bubbleSize))
|
||||
expandedView.updateDimensions()
|
||||
}
|
||||
|
||||
fun updateBtnTheme() {
|
||||
val res = context.resources
|
||||
|
||||
// Set overflow button accent color, dot color
|
||||
val typedValue = TypedValue()
|
||||
context.theme.resolveAttribute(android.R.attr.colorAccent, typedValue, true)
|
||||
|
||||
val colorAccent = res.getColor(typedValue.resourceId)
|
||||
overflowBtn.getDrawable()?.setTint(colorAccent)
|
||||
dotColor = colorAccent
|
||||
|
||||
// Set button and activity background color
|
||||
val nightMode = (res.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
||||
== Configuration.UI_MODE_NIGHT_YES)
|
||||
val bg = ColorDrawable(res.getColor(
|
||||
if (nightMode) R.color.bubbles_dark else R.color.bubbles_light))
|
||||
|
||||
// Set button icon
|
||||
val iconFactory = BubbleIconFactory(context)
|
||||
val fg = InsetDrawable(overflowBtn.getDrawable(),
|
||||
bitmapSize - iconBitmapSize /* inset */)
|
||||
bitmap = iconFactory.createBadgedIconBitmap(AdaptiveIconDrawable(bg, fg),
|
||||
null /* user */, true /* shrinkNonAdaptiveIcons */).icon
|
||||
|
||||
// Set dot path
|
||||
dotPath = PathParser.createPathFromPathData(
|
||||
res.getString(com.android.internal.R.string.config_icon_mask))
|
||||
val scale = iconFactory.normalizer.getScale(overflowBtn.getDrawable(),
|
||||
null /* outBounds */, null /* path */, null /* outMaskShape */)
|
||||
val radius = BadgedImageView.DEFAULT_PATH_SIZE / 2f
|
||||
val matrix = Matrix()
|
||||
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
|
||||
radius /* pivot y */)
|
||||
dotPath?.transform(matrix)
|
||||
overflowBtn.setRenderedBubble(this)
|
||||
}
|
||||
|
||||
fun setVisible(visible: Int) {
|
||||
overflowBtn.visibility = visible
|
||||
}
|
||||
|
||||
override fun getExpandedView(): BubbleExpandedView? {
|
||||
return expandedView
|
||||
}
|
||||
|
||||
override fun getDotColor(): Int {
|
||||
return dotColor
|
||||
}
|
||||
|
||||
override fun getBadgedImage(): Bitmap? {
|
||||
return bitmap
|
||||
}
|
||||
|
||||
override fun showDot(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getDotPath(): Path? {
|
||||
return dotPath
|
||||
}
|
||||
|
||||
override fun setContentVisibility(visible: Boolean) {
|
||||
expandedView.setContentVisibility(visible)
|
||||
}
|
||||
|
||||
override fun getIconView(): View? {
|
||||
return overflowBtn
|
||||
}
|
||||
|
||||
override fun getKey(): String {
|
||||
return KEY
|
||||
}
|
||||
|
||||
override fun getDisplayId(): Int {
|
||||
return expandedView.virtualDisplayId
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmField val KEY = "Overflow"
|
||||
}
|
||||
}
|
||||
@@ -907,7 +907,16 @@ public class BubbleStackView extends FrameLayout
|
||||
setFocusable(true);
|
||||
mBubbleContainer.bringToFront();
|
||||
|
||||
setUpOverflow();
|
||||
mBubbleOverflow = new BubbleOverflow(getContext(), this);
|
||||
mBubbleContainer.addView(mBubbleOverflow.getIconView(),
|
||||
mBubbleContainer.getChildCount() /* index */,
|
||||
new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
updateOverflow();
|
||||
mBubbleOverflow.getIconView().setOnClickListener((View v) -> {
|
||||
setSelectedBubble(mBubbleOverflow);
|
||||
showManageMenu(false);
|
||||
});
|
||||
|
||||
mOnImeVisibilityChanged = onImeVisibilityChanged;
|
||||
mHideCurrentInputMethodCallback = hideCurrentInputMethodCallback;
|
||||
@@ -933,7 +942,7 @@ public class BubbleStackView extends FrameLayout
|
||||
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
|
||||
mExpandedAnimationController.updateResources(mOrientation, mDisplaySize);
|
||||
mStackAnimationController.updateResources(mOrientation);
|
||||
mBubbleOverflow.updateDimensions();
|
||||
mBubbleOverflow.updateResources();
|
||||
|
||||
// Need to update the padding around the view
|
||||
WindowInsets insets = getRootWindowInsets();
|
||||
@@ -1187,32 +1196,21 @@ public class BubbleStackView extends FrameLayout
|
||||
addView(mFlyout, new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
|
||||
}
|
||||
|
||||
private void setUpOverflow() {
|
||||
int overflowBtnIndex = 0;
|
||||
if (mBubbleOverflow == null) {
|
||||
mBubbleOverflow = new BubbleOverflow(getContext());
|
||||
mBubbleOverflow.setUpOverflow(mBubbleContainer, this);
|
||||
} else {
|
||||
mBubbleContainer.removeView(mBubbleOverflow.getIconView());
|
||||
mBubbleOverflow.setUpOverflow(mBubbleContainer, this);
|
||||
overflowBtnIndex = mBubbleContainer.getChildCount();
|
||||
}
|
||||
mBubbleContainer.addView(mBubbleOverflow.getIconView(), overflowBtnIndex,
|
||||
new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
|
||||
mBubbleOverflow.getIconView().setOnClickListener(v -> {
|
||||
setSelectedBubble(mBubbleOverflow);
|
||||
showManageMenu(false);
|
||||
});
|
||||
private void updateOverflow() {
|
||||
mBubbleOverflow.update();
|
||||
mBubbleContainer.reorderView(mBubbleOverflow.getIconView(),
|
||||
mBubbleContainer.getChildCount() - 1 /* index */);
|
||||
updateOverflowVisibility();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle theme changes.
|
||||
*/
|
||||
public void onThemeChanged() {
|
||||
setUpFlyout();
|
||||
setUpOverflow();
|
||||
setUpUserEducation();
|
||||
setUpManageMenu();
|
||||
updateOverflow();
|
||||
updateExpandedViewTheme();
|
||||
}
|
||||
|
||||
@@ -1261,7 +1259,7 @@ public class BubbleStackView extends FrameLayout
|
||||
|
||||
/** Respond to the display size change by recalculating view size and location. */
|
||||
public void onDisplaySizeChanged() {
|
||||
setUpOverflow();
|
||||
updateOverflow();
|
||||
|
||||
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
|
||||
wm.getDefaultDisplay().getRealSize(mDisplaySize);
|
||||
|
||||
Reference in New Issue
Block a user