mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 23:36:47 +00:00
Merge "Animate bubble bar icon sizes and padding" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
be4e591fac
@@ -45,8 +45,6 @@
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginHorizontal="@dimen/transient_taskbar_bottom_margin"
|
||||
android:paddingTop="@dimen/bubblebar_pointer_visible_size"
|
||||
android:paddingEnd="@dimen/taskbar_icon_spacing"
|
||||
android:paddingStart="@dimen/taskbar_icon_spacing"
|
||||
android:visibility="gone"
|
||||
android:gravity="center"
|
||||
android:clipChildren="false"
|
||||
|
||||
@@ -123,22 +123,23 @@ class BubbleBarBackground(context: Context, private var backgroundHeight: Float)
|
||||
)
|
||||
// Create background path
|
||||
val backgroundPath = Path()
|
||||
val topOffset = backgroundHeight - bounds.height().toFloat()
|
||||
val radius = backgroundHeight / 2f
|
||||
val left = bounds.left + (if (anchorLeft) 0f else bounds.width().toFloat() - width)
|
||||
val right = bounds.left + (if (anchorLeft) width else bounds.width().toFloat())
|
||||
val top = bounds.top + arrowVisibleHeight
|
||||
val top = bounds.top - topOffset + arrowVisibleHeight
|
||||
|
||||
val bottom = bounds.top + bounds.height().toFloat()
|
||||
backgroundPath.addRoundRect(left, top, right, bottom, radius, radius, Path.Direction.CW)
|
||||
addArrowPathIfNeeded(backgroundPath)
|
||||
addArrowPathIfNeeded(backgroundPath, topOffset)
|
||||
|
||||
// Draw background.
|
||||
canvas.drawPath(backgroundPath, fillPaint)
|
||||
canvas.drawPath(backgroundPath, strokePaint)
|
||||
|
||||
canvas.restore()
|
||||
}
|
||||
|
||||
private fun addArrowPathIfNeeded(sourcePath: Path) {
|
||||
private fun addArrowPathIfNeeded(sourcePath: Path, topOffset: Float) {
|
||||
if (!showingArrow || arrowHeightFraction <= 0) return
|
||||
val arrowPath = Path()
|
||||
RoundedArrowDrawable.addDownPointingRoundedTriangleToPath(
|
||||
@@ -153,7 +154,7 @@ class BubbleBarBackground(context: Context, private var backgroundHeight: Float)
|
||||
arrowPath.transform(pathTransform)
|
||||
// shift to arrow position
|
||||
val arrowStart = bounds.left + arrowPositionX - (arrowWidth / 2f)
|
||||
val arrowTop = (1 - arrowHeightFraction) * arrowVisibleHeight
|
||||
val arrowTop = (1 - arrowHeightFraction) * arrowVisibleHeight - topOffset
|
||||
arrowPath.offset(arrowStart, arrowTop)
|
||||
// union with rectangle
|
||||
sourcePath.op(arrowPath, Path.Op.UNION)
|
||||
@@ -180,7 +181,7 @@ class BubbleBarBackground(context: Context, private var backgroundHeight: Float)
|
||||
fillPaint.colorFilter = colorFilter
|
||||
}
|
||||
|
||||
fun setHeight(newHeight: Float) {
|
||||
fun setBackgroundHeight(newHeight: Float) {
|
||||
backgroundHeight = newHeight
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
@@ -44,6 +45,7 @@ import androidx.dynamicanimation.animation.SpringForce;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.SpringAnimationBuilder;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.wm.shell.Flags;
|
||||
import com.android.wm.shell.common.bubbles.BubbleBarLocation;
|
||||
|
||||
import java.util.List;
|
||||
@@ -85,6 +87,7 @@ public class BubbleBarView extends FrameLayout {
|
||||
private static final int MAX_VISIBLE_BUBBLES_COLLAPSED = 2;
|
||||
private static final int ARROW_POSITION_ANIMATION_DURATION_MS = 200;
|
||||
private static final int WIDTH_ANIMATION_DURATION_MS = 200;
|
||||
private static final int SCALE_ANIMATION_DURATION_MS = 200;
|
||||
|
||||
private static final long FADE_OUT_ANIM_ALPHA_DURATION_MS = 50L;
|
||||
private static final long FADE_OUT_ANIM_ALPHA_DELAY_MS = 50L;
|
||||
@@ -135,13 +138,12 @@ public class BubbleBarView extends FrameLayout {
|
||||
private float mBubbleBarPadding;
|
||||
// The size of a bubble in the bar
|
||||
private float mIconSize;
|
||||
// The scale of bubble icons
|
||||
private float mIconScale = 1f;
|
||||
// The elevation of the bubbles within the bar
|
||||
private final float mBubbleElevation;
|
||||
private final float mDragElevation;
|
||||
private final int mPointerSize;
|
||||
|
||||
private final Rect mTempBackgroundBounds = new Rect();
|
||||
|
||||
// Whether the bar is expanded (i.e. the bubble activity is being displayed).
|
||||
private boolean mIsBarExpanded = false;
|
||||
// The currently selected bubble view.
|
||||
@@ -162,7 +164,8 @@ public class BubbleBarView extends FrameLayout {
|
||||
/** An animator used for scaling in a new bubble to the bubble bar while expanded. */
|
||||
@Nullable
|
||||
private ValueAnimator mNewBubbleScaleInAnimator = null;
|
||||
|
||||
@Nullable
|
||||
private ValueAnimator mScalePaddingAnimator;
|
||||
@Nullable
|
||||
private Animator mBubbleBarLocationAnimator = null;
|
||||
|
||||
@@ -217,42 +220,74 @@ public class BubbleBarView extends FrameLayout {
|
||||
setBackgroundDrawable(mBubbleBarBackground);
|
||||
|
||||
mWidthAnimator.setDuration(WIDTH_ANIMATION_DURATION_MS);
|
||||
mWidthAnimator.addUpdateListener(animation -> {
|
||||
updateBubblesLayoutProperties(mBubbleBarLocation);
|
||||
invalidate();
|
||||
});
|
||||
mWidthAnimator.addListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mBubbleBarBackground.showArrow(mIsBarExpanded);
|
||||
if (!mIsBarExpanded && mReorderRunnable != null) {
|
||||
mReorderRunnable.run();
|
||||
mReorderRunnable = null;
|
||||
}
|
||||
// If the bar was just collapsed and the overflow was the last bubble that was
|
||||
// selected, set the first bubble as selected.
|
||||
if (!mIsBarExpanded && mUpdateSelectedBubbleAfterCollapse != null
|
||||
&& mSelectedBubbleView != null
|
||||
&& mSelectedBubbleView.getBubble() instanceof BubbleBarOverflow) {
|
||||
BubbleView firstBubble = (BubbleView) getChildAt(0);
|
||||
mUpdateSelectedBubbleAfterCollapse.accept(firstBubble.getBubble().getKey());
|
||||
}
|
||||
updateWidth();
|
||||
}
|
||||
addAnimationCallBacks(mWidthAnimator,
|
||||
/* onStart= */ () -> mBubbleBarBackground.showArrow(true),
|
||||
/* onEnd= */ () -> {
|
||||
mBubbleBarBackground.showArrow(mIsBarExpanded);
|
||||
if (!mIsBarExpanded && mReorderRunnable != null) {
|
||||
mReorderRunnable.run();
|
||||
mReorderRunnable = null;
|
||||
}
|
||||
// If the bar was just collapsed and the overflow was the last bubble that was
|
||||
// selected, set the first bubble as selected.
|
||||
if (!mIsBarExpanded && mUpdateSelectedBubbleAfterCollapse != null
|
||||
&& mSelectedBubbleView != null
|
||||
&& mSelectedBubbleView.getBubble() instanceof BubbleBarOverflow) {
|
||||
BubbleView firstBubble = (BubbleView) getChildAt(0);
|
||||
mUpdateSelectedBubbleAfterCollapse.accept(firstBubble.getBubble().getKey());
|
||||
}
|
||||
updateWidth();
|
||||
},
|
||||
/* onUpdate= */ animator -> {
|
||||
updateBubblesLayoutProperties(mBubbleBarLocation);
|
||||
invalidate();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mBubbleBarBackground.showArrow(true);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Animates icon sizes and spacing between icons and bubble bar borders.
|
||||
*
|
||||
* @param newIconSize new icon size
|
||||
* @param newBubbleBarPadding spacing between icons and bubble bar borders.
|
||||
*/
|
||||
public void animateBubbleBarIconSize(float newIconSize, float newBubbleBarPadding) {
|
||||
if (!isIconSizeOrPaddingUpdated(newIconSize, newBubbleBarPadding)) {
|
||||
return;
|
||||
}
|
||||
if (!Flags.animateBubbleSizeChange()) {
|
||||
setIconSizeAndPadding(newIconSize, newBubbleBarPadding);
|
||||
}
|
||||
if (mScalePaddingAnimator != null && mScalePaddingAnimator.isRunning()) {
|
||||
mScalePaddingAnimator.cancel();
|
||||
}
|
||||
ValueAnimator scalePaddingAnimator = ValueAnimator.ofFloat(0f, 1f);
|
||||
scalePaddingAnimator.setDuration(SCALE_ANIMATION_DURATION_MS);
|
||||
boolean isPaddingUpdated = isPaddingUpdated(newBubbleBarPadding);
|
||||
boolean isIconSizeUpdated = isIconSizeUpdated(newIconSize);
|
||||
float initialScale = mIconScale;
|
||||
float initialPadding = mBubbleBarPadding;
|
||||
float targetScale = newIconSize / getScaledIconSize();
|
||||
|
||||
addAnimationCallBacks(scalePaddingAnimator,
|
||||
/* onStart= */ null,
|
||||
/* onEnd= */ () -> setIconSizeAndPadding(newIconSize, newBubbleBarPadding),
|
||||
/* onUpdate= */ animator -> {
|
||||
float transitionProgress = (float) animator.getAnimatedValue();
|
||||
if (isIconSizeUpdated) {
|
||||
mIconScale =
|
||||
initialScale + (targetScale - initialScale) * transitionProgress;
|
||||
}
|
||||
if (isPaddingUpdated) {
|
||||
mBubbleBarPadding = initialPadding
|
||||
+ (newBubbleBarPadding - initialPadding) * transitionProgress;
|
||||
}
|
||||
updateBubblesLayoutProperties(mBubbleBarLocation);
|
||||
invalidate();
|
||||
});
|
||||
scalePaddingAnimator.start();
|
||||
mScalePaddingAnimator = scalePaddingAnimator;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -267,28 +302,37 @@ public class BubbleBarView extends FrameLayout {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets new icon size and spacing between icons and bubble bar borders.
|
||||
* Sets new icon sizes and newBubbleBarPadding between icons and bubble bar borders.
|
||||
*
|
||||
* @param newIconSize new icon size
|
||||
* @param spacing spacing between icons and bubble bar borders.
|
||||
* @param newIconSize new icon size
|
||||
* @param newBubbleBarPadding newBubbleBarPadding between icons and bubble bar borders.
|
||||
*/
|
||||
// TODO(b/335575529): animate bubble bar icons size change
|
||||
public void setIconSizeAndPadding(float newIconSize, float spacing) {
|
||||
public void setIconSizeAndPadding(float newIconSize, float newBubbleBarPadding) {
|
||||
// TODO(b/335457839): handle new bubble animation during the size change
|
||||
mBubbleBarPadding = spacing;
|
||||
if (!isIconSizeOrPaddingUpdated(newIconSize, newBubbleBarPadding)) {
|
||||
return;
|
||||
}
|
||||
mIconScale = 1f;
|
||||
mBubbleBarPadding = newBubbleBarPadding;
|
||||
mIconSize = newIconSize;
|
||||
int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View childView = getChildAt(i);
|
||||
childView.setScaleY(mIconScale);
|
||||
childView.setScaleY(mIconScale);
|
||||
FrameLayout.LayoutParams params = (LayoutParams) childView.getLayoutParams();
|
||||
params.height = (int) mIconSize;
|
||||
params.width = (int) mIconSize;
|
||||
childView.setLayoutParams(params);
|
||||
}
|
||||
mBubbleBarBackground.setHeight(getBubbleBarExpandedHeight());
|
||||
mBubbleBarBackground.setBackgroundHeight(getBubbleBarHeight());
|
||||
updateLayoutParams();
|
||||
}
|
||||
|
||||
private float getScaledIconSize() {
|
||||
return mIconSize * mIconScale;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
@@ -698,6 +742,11 @@ public class BubbleBarView extends FrameLayout {
|
||||
setLayoutParams(lp);
|
||||
}
|
||||
|
||||
private float getBubbleBarHeight() {
|
||||
return mIsBarExpanded ? getBubbleBarExpandedHeight()
|
||||
: getBubbleBarCollapsedHeight();
|
||||
}
|
||||
|
||||
/** @return the horizontal margin between the bubble bar and the edge of the screen. */
|
||||
int getHorizontalMargin() {
|
||||
LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
|
||||
@@ -714,7 +763,10 @@ public class BubbleBarView extends FrameLayout {
|
||||
final float expandedWidth = expandedWidth();
|
||||
final float collapsedWidth = collapsedWidth();
|
||||
int bubbleCount = getChildCount();
|
||||
final float ty = (mBubbleBarBounds.height() - mIconSize) / 2f;
|
||||
float viewBottom = mBubbleBarBounds.height() + (isExpanded() ? mPointerSize : 0);
|
||||
float bubbleBarAnimatedTop = viewBottom - getBubbleBarHeight();
|
||||
// When translating X & Y the scale is ignored, so need to deduct it from the translations
|
||||
final float ty = bubbleBarAnimatedTop + mBubbleBarPadding - getScaleIconShift();
|
||||
final boolean animate = getVisibility() == VISIBLE;
|
||||
final boolean onLeft = bubbleBarLocation.isOnLeft(isLayoutRtl());
|
||||
// elevation state is opposite to widthState - when expanded all icons are flat
|
||||
@@ -729,8 +781,9 @@ public class BubbleBarView extends FrameLayout {
|
||||
bv.setDragTranslationX(0f);
|
||||
bv.setOffsetX(0f);
|
||||
|
||||
bv.setScaleX(mIconScale);
|
||||
bv.setScaleY(mIconScale);
|
||||
bv.setTranslationY(ty);
|
||||
|
||||
// the position of the bubble when the bar is fully expanded
|
||||
final float expandedX = getExpandedBubbleTranslationX(i, bubbleCount, onLeft);
|
||||
// the position of the bubble when the bar is fully collapsed
|
||||
@@ -795,21 +848,28 @@ public class BubbleBarView extends FrameLayout {
|
||||
mBubbleBarBackground.setArrowPosition(arrowPosition);
|
||||
mBubbleBarBackground.setArrowHeightFraction(widthState);
|
||||
mBubbleBarBackground.setWidth(interpolatedWidth);
|
||||
mBubbleBarBackground.setBackgroundHeight(getBubbleBarExpandedHeight());
|
||||
}
|
||||
|
||||
private float getScaleIconShift() {
|
||||
return (mIconSize - getScaledIconSize()) / 2;
|
||||
}
|
||||
|
||||
private float getExpandedBubbleTranslationX(int bubbleIndex, int bubbleCount, boolean onLeft) {
|
||||
if (bubbleIndex < 0 || bubbleIndex >= bubbleCount) {
|
||||
return 0;
|
||||
}
|
||||
final float iconAndSpacing = mIconSize + mExpandedBarIconsSpacing;
|
||||
final float iconAndSpacing = getScaledIconSize() + mExpandedBarIconsSpacing;
|
||||
float translationX;
|
||||
if (mNewBubbleScaleInAnimator != null && mNewBubbleScaleInAnimator.isRunning()) {
|
||||
return getExpandedBubbleTranslationXDuringScaleAnimation(
|
||||
translationX = getExpandedBubbleTranslationXDuringScaleAnimation(
|
||||
bubbleIndex, bubbleCount, onLeft);
|
||||
} else if (onLeft) {
|
||||
return (bubbleCount - bubbleIndex - 1) * iconAndSpacing;
|
||||
translationX = mBubbleBarPadding + (bubbleCount - bubbleIndex - 1) * iconAndSpacing;
|
||||
} else {
|
||||
return bubbleIndex * iconAndSpacing;
|
||||
translationX = mBubbleBarPadding + bubbleIndex * iconAndSpacing;
|
||||
}
|
||||
return translationX - getScaleIconShift();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -830,17 +890,17 @@ public class BubbleBarView extends FrameLayout {
|
||||
// compiler doesn't know that.
|
||||
return 0;
|
||||
}
|
||||
final float iconAndSpacing = mIconSize + mExpandedBarIconsSpacing;
|
||||
final float iconAndSpacing = getScaledIconSize() + mExpandedBarIconsSpacing;
|
||||
final float newBubbleScale = mNewBubbleScaleInAnimator.getAnimatedFraction();
|
||||
// the new bubble is scaling in from the center, so we need to adjust its translation so
|
||||
// that the distance to the adjacent bubble scales at the same rate.
|
||||
final float pivotAdjustment = -(1 - newBubbleScale) * mIconSize / 2f;
|
||||
final float pivotAdjustment = -(1 - newBubbleScale) * getScaledIconSize() / 2f;
|
||||
|
||||
if (onLeft) {
|
||||
if (bubbleIndex == 0) {
|
||||
// this is the animating bubble. use scaled spacing between it and the bubble to
|
||||
// its left
|
||||
return (bubbleCount - 1) * mIconSize
|
||||
return (bubbleCount - 1) * getScaledIconSize()
|
||||
+ (bubbleCount - 2) * mExpandedBarIconsSpacing
|
||||
+ newBubbleScale * mExpandedBarIconsSpacing
|
||||
+ pivotAdjustment;
|
||||
@@ -862,13 +922,16 @@ public class BubbleBarView extends FrameLayout {
|
||||
if (bubbleIndex < 0 || bubbleIndex >= bubbleCount) {
|
||||
return 0;
|
||||
}
|
||||
float translationX;
|
||||
if (onLeft) {
|
||||
// Shift the first bubble only if there are more bubbles in addition to overflow
|
||||
return bubbleIndex == 0 && bubbleCount > MAX_VISIBLE_BUBBLES_COLLAPSED
|
||||
? mIconOverlapAmount : 0;
|
||||
translationX = mBubbleBarPadding + (
|
||||
bubbleIndex == 0 && bubbleCount > MAX_VISIBLE_BUBBLES_COLLAPSED
|
||||
? mIconOverlapAmount : 0);
|
||||
} else {
|
||||
return bubbleIndex == 0 ? 0 : mIconOverlapAmount;
|
||||
translationX = mBubbleBarPadding + (bubbleIndex == 0 ? 0 : mIconOverlapAmount);
|
||||
}
|
||||
return translationX - getScaleIconShift();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -976,7 +1039,7 @@ public class BubbleBarView extends FrameLayout {
|
||||
final int index = indexOfChild(mSelectedBubbleView);
|
||||
final float selectedBubbleTranslationX = getExpandedBubbleTranslationX(
|
||||
index, getChildCount(), bubbleBarLocation.isOnLeft(isLayoutRtl()));
|
||||
return getPaddingStart() + selectedBubbleTranslationX + mIconSize / 2f;
|
||||
return selectedBubbleTranslationX + mIconSize / 2f;
|
||||
}
|
||||
|
||||
private float arrowPositionForSelectedWhenCollapsed(BubbleBarLocation bubbleBarLocation) {
|
||||
@@ -990,7 +1053,7 @@ public class BubbleBarView extends FrameLayout {
|
||||
bubblePosition = index >= MAX_VISIBLE_BUBBLES_COLLAPSED
|
||||
? MAX_VISIBLE_BUBBLES_COLLAPSED - 1 : index;
|
||||
}
|
||||
return getPaddingStart() + bubblePosition * (mIconOverlapAmount) + mIconSize / 2f;
|
||||
return mBubbleBarPadding + bubblePosition * (mIconOverlapAmount) + getScaledIconSize() / 2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1038,7 +1101,6 @@ public class BubbleBarView extends FrameLayout {
|
||||
*/
|
||||
public float expandedWidth() {
|
||||
final int childCount = getChildCount();
|
||||
final int horizontalPadding = getPaddingStart() + getPaddingEnd();
|
||||
// spaces amount is less than child count by 1, or 0 if no child views
|
||||
final float totalSpace;
|
||||
final float totalIconSize;
|
||||
@@ -1047,22 +1109,22 @@ public class BubbleBarView extends FrameLayout {
|
||||
// expanded, so we have at least 2 bubbles in the bubble bar.
|
||||
final float newBubbleScale = mNewBubbleScaleInAnimator.getAnimatedFraction();
|
||||
totalSpace = (childCount - 2 + newBubbleScale) * mExpandedBarIconsSpacing;
|
||||
totalIconSize = (childCount - 1 + newBubbleScale) * mIconSize;
|
||||
totalIconSize = (childCount - 1 + newBubbleScale) * getScaledIconSize();
|
||||
} else {
|
||||
totalSpace = Math.max(childCount - 1, 0) * mExpandedBarIconsSpacing;
|
||||
totalIconSize = childCount * mIconSize;
|
||||
totalIconSize = childCount * getScaledIconSize();
|
||||
}
|
||||
return totalIconSize + totalSpace + horizontalPadding;
|
||||
return totalIconSize + totalSpace + 2 * mBubbleBarPadding;
|
||||
}
|
||||
|
||||
private float collapsedWidth() {
|
||||
final int childCount = getChildCount();
|
||||
final int horizontalPadding = getPaddingStart() + getPaddingEnd();
|
||||
final float horizontalPadding = 2 * mBubbleBarPadding;
|
||||
// If there are more than 2 bubbles, the first 2 should be visible when collapsed.
|
||||
// Otherwise just the first bubble should be visible because we don't show the overflow.
|
||||
return childCount > MAX_VISIBLE_BUBBLES_COLLAPSED
|
||||
? mIconSize + mIconOverlapAmount + horizontalPadding
|
||||
: mIconSize + horizontalPadding;
|
||||
? getScaledIconSize() + mIconOverlapAmount + horizontalPadding
|
||||
: getScaledIconSize() + horizontalPadding;
|
||||
}
|
||||
|
||||
private float getBubbleBarExpandedHeight() {
|
||||
@@ -1071,7 +1133,7 @@ public class BubbleBarView extends FrameLayout {
|
||||
|
||||
float getBubbleBarCollapsedHeight() {
|
||||
// the pointer is invisible when collapsed
|
||||
return mIconSize + mBubbleBarPadding * 2;
|
||||
return getScaledIconSize() + mBubbleBarPadding * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1103,6 +1165,7 @@ public class BubbleBarView extends FrameLayout {
|
||||
return mIsAnimatingNewBubble;
|
||||
}
|
||||
|
||||
|
||||
private boolean hasOverview() {
|
||||
// Overview is always the last bubble
|
||||
View lastChild = getChildAt(getChildCount() - 1);
|
||||
@@ -1144,6 +1207,46 @@ public class BubbleBarView extends FrameLayout {
|
||||
setContentDescription(contentDesc);
|
||||
}
|
||||
|
||||
private boolean isIconSizeOrPaddingUpdated(float newIconSize, float newBubbleBarPadding) {
|
||||
return isIconSizeUpdated(newIconSize) || isPaddingUpdated(newBubbleBarPadding);
|
||||
}
|
||||
|
||||
private boolean isIconSizeUpdated(float newIconSize) {
|
||||
return Float.compare(mIconSize, newIconSize) != 0;
|
||||
}
|
||||
|
||||
private boolean isPaddingUpdated(float newBubbleBarPadding) {
|
||||
return Float.compare(mBubbleBarPadding, newBubbleBarPadding) != 0;
|
||||
}
|
||||
|
||||
private void addAnimationCallBacks(@NonNull ValueAnimator animator,
|
||||
@Nullable Runnable onStart,
|
||||
@Nullable Runnable onEnd,
|
||||
@Nullable ValueAnimator.AnimatorUpdateListener onUpdate) {
|
||||
if (onUpdate != null) animator.addUpdateListener(onUpdate);
|
||||
animator.addListener(new Animator.AnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animator) {
|
||||
if (onStart != null) onStart.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
if (onEnd != null) onEnd.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animator) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Interface for BubbleBarView to communicate with its controller. */
|
||||
interface Controller {
|
||||
|
||||
|
||||
@@ -108,9 +108,11 @@ public class BubbleBarViewController {
|
||||
mBubbleDragController = bubbleControllers.bubbleDragController;
|
||||
mTaskbarStashController = controllers.taskbarStashController;
|
||||
mTaskbarInsetsController = controllers.taskbarInsetsController;
|
||||
mBubbleBarViewAnimator = new BubbleBarViewAnimator(mBarView, mBubbleStashController);
|
||||
|
||||
mActivity.addOnDeviceProfileChangeListener(dp -> setBubbleBarIconSize(dp.taskbarIconSize));
|
||||
setBubbleBarIconSize(mActivity.getDeviceProfile().taskbarIconSize);
|
||||
mActivity.addOnDeviceProfileChangeListener(
|
||||
dp -> updateBubbleBarIconSize(dp.taskbarIconSize, /* animate= */ true));
|
||||
updateBubbleBarIconSize(mActivity.getDeviceProfile().taskbarIconSize, /* animate= */ false);
|
||||
mBubbleBarScale.updateValue(1f);
|
||||
mBubbleClickListener = v -> onBubbleClicked(v);
|
||||
mBubbleBarClickListener = v -> onBubbleBarClicked();
|
||||
@@ -123,8 +125,6 @@ public class BubbleBarViewController {
|
||||
mBoundsChangeListener.onBoundsChanged();
|
||||
}
|
||||
});
|
||||
|
||||
mBubbleBarViewAnimator = new BubbleBarViewAnimator(mBarView, mBubbleStashController);
|
||||
mBarView.setController(new BubbleBarView.Controller() {
|
||||
@Override
|
||||
public float getBubbleBarTranslationY() {
|
||||
@@ -299,33 +299,6 @@ public class BubbleBarViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private void setBubbleBarIconSize(int newIconSize) {
|
||||
if (newIconSize == mIconSize) {
|
||||
return;
|
||||
}
|
||||
Resources res = mActivity.getResources();
|
||||
DisplayMetrics dm = res.getDisplayMetrics();
|
||||
float smallIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
APP_ICON_SMALL_DP, dm);
|
||||
float mediumIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
APP_ICON_MEDIUM_DP, dm);
|
||||
float largeIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
APP_ICON_LARGE_DP, dm);
|
||||
float smallMediumThreshold = (smallIconSize + mediumIconSize) / 2f;
|
||||
float mediumLargeThreshold = (mediumIconSize + largeIconSize) / 2f;
|
||||
mIconSize = newIconSize <= smallMediumThreshold
|
||||
? res.getDimensionPixelSize(R.dimen.bubblebar_icon_size_small) :
|
||||
res.getDimensionPixelSize(R.dimen.bubblebar_icon_size);
|
||||
float bubbleBarPadding = newIconSize >= mediumLargeThreshold
|
||||
? res.getDimensionPixelSize(R.dimen.bubblebar_icon_spacing_large) :
|
||||
res.getDimensionPixelSize(R.dimen.bubblebar_icon_spacing);
|
||||
|
||||
mBarView.setIconSizeAndPadding(mIconSize, bubbleBarPadding);
|
||||
mBarView.setPadding((int) bubbleBarPadding, mBarView.getPaddingTop(),
|
||||
(int) bubbleBarPadding,
|
||||
mBarView.getPaddingBottom());
|
||||
}
|
||||
|
||||
/** Sets a callback that updates the selected bubble after the bubble bar collapses. */
|
||||
public void setUpdateSelectedBubbleAfterCollapse(
|
||||
Consumer<String> updateSelectedBubbleAfterCollapse) {
|
||||
@@ -360,6 +333,30 @@ public class BubbleBarViewController {
|
||||
// Modifying view related properties.
|
||||
//
|
||||
|
||||
private void updateBubbleBarIconSize(int newIconSize, boolean animate) {
|
||||
Resources res = mActivity.getResources();
|
||||
DisplayMetrics dm = res.getDisplayMetrics();
|
||||
float smallIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
APP_ICON_SMALL_DP, dm);
|
||||
float mediumIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
APP_ICON_MEDIUM_DP, dm);
|
||||
float largeIconSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
APP_ICON_LARGE_DP, dm);
|
||||
float smallMediumThreshold = (smallIconSize + mediumIconSize) / 2f;
|
||||
float mediumLargeThreshold = (mediumIconSize + largeIconSize) / 2f;
|
||||
mIconSize = newIconSize <= smallMediumThreshold
|
||||
? res.getDimensionPixelSize(R.dimen.bubblebar_icon_size_small) :
|
||||
res.getDimensionPixelSize(R.dimen.bubblebar_icon_size);
|
||||
float bubbleBarPadding = newIconSize >= mediumLargeThreshold
|
||||
? res.getDimensionPixelSize(R.dimen.bubblebar_icon_spacing_large) :
|
||||
res.getDimensionPixelSize(R.dimen.bubblebar_icon_spacing);
|
||||
if (animate) {
|
||||
mBarView.animateBubbleBarIconSize(mIconSize, bubbleBarPadding);
|
||||
} else {
|
||||
mBarView.setIconSizeAndPadding(mIconSize, bubbleBarPadding);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the translation of the bubble bar during the swipe up gesture.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user