Merge remote-tracking branch 'aosp/android12L-release' into 12.1-dev
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
|
||||
package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_ICON_LABEL_AUTO_SCALING;
|
||||
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
|
||||
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
|
||||
|
||||
@@ -34,6 +35,8 @@ import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.icu.text.MessageFormat;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils.TruncateAt;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Property;
|
||||
@@ -67,9 +70,12 @@ import com.android.launcher3.model.data.SearchActionItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.BubbleTextHolder;
|
||||
import com.android.launcher3.views.IconLabelDotView;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
|
||||
import app.lawnchair.font.FontManager;
|
||||
import app.lawnchair.util.LawnchairUtilsKt;
|
||||
@@ -89,12 +95,19 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
private static final int DISPLAY_SEARCH_RESULT = 6;
|
||||
private static final int DISPLAY_SEARCH_RESULT_SMALL = 7;
|
||||
|
||||
private static final float MIN_LETTER_SPACING = -0.05f;
|
||||
private static final int MAX_SEARCH_LOOP_COUNT = 20;
|
||||
|
||||
private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
|
||||
private static final float HIGHLIGHT_SCALE = 1.16f;
|
||||
|
||||
private final PointF mTranslationForReorderBounce = new PointF(0, 0);
|
||||
private final PointF mTranslationForReorderPreview = new PointF(0, 0);
|
||||
|
||||
private float mTranslationXForTaskbarAlignmentAnimation = 0f;
|
||||
|
||||
private final PointF mTranslationForMoveFromCenterAnimation = new PointF(0, 0);
|
||||
|
||||
private float mScaleForReorderBounce = 1f;
|
||||
|
||||
private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
|
||||
@@ -133,6 +146,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
private final CheckLongPressHelper mLongPressHelper;
|
||||
|
||||
private final boolean mLayoutHorizontal;
|
||||
private final boolean mIsRtl;
|
||||
private final int mIconSize;
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
@@ -160,6 +174,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
private HandlerRunnable mIconLoadRequest;
|
||||
|
||||
private boolean mEnableIconUpdateAnimation = false;
|
||||
private BubbleTextHolder mBubbleTextHolder;
|
||||
|
||||
public BubbleTextView(Context context) {
|
||||
this(context, null, 0);
|
||||
@@ -176,6 +191,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.BubbleTextView, defStyle, 0);
|
||||
mLayoutHorizontal = a.getBoolean(R.styleable.BubbleTextView_layoutHorizontal, false);
|
||||
mIsRtl = (getResources().getConfiguration().getLayoutDirection()
|
||||
== View.LAYOUT_DIRECTION_RTL);
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
|
||||
mDisplay = a.getInteger(R.styleable.BubbleTextView_iconDisplay, DISPLAY_WORKSPACE);
|
||||
@@ -261,9 +278,27 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
|
||||
@UiThread
|
||||
public void applyFromWorkspaceItem(WorkspaceItemInfo info) {
|
||||
applyFromWorkspaceItem(info, /* animate = */ false, /* staggerIndex = */ 0);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
public void applyFromWorkspaceItem(WorkspaceItemInfo info, boolean animate, int staggerIndex) {
|
||||
applyFromWorkspaceItem(info, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the newInfo differs from the current getTag().
|
||||
*/
|
||||
public boolean shouldAnimateIconChange(WorkspaceItemInfo newInfo) {
|
||||
WorkspaceItemInfo oldInfo = getTag() instanceof WorkspaceItemInfo
|
||||
? (WorkspaceItemInfo) getTag()
|
||||
: null;
|
||||
boolean changedIcons = oldInfo != null && oldInfo.getTargetComponent() != null
|
||||
&& newInfo.getTargetComponent() != null
|
||||
&& !oldInfo.getTargetComponent().equals(newInfo.getTargetComponent());
|
||||
return changedIcons && isShown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
|
||||
if (delegate instanceof LauncherAccessibilityDelegate) {
|
||||
@@ -279,7 +314,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
@UiThread
|
||||
public void applyFromWorkspaceItem(WorkspaceItemInfo info, boolean promiseStateChanged) {
|
||||
applyIconAndLabel(info);
|
||||
setTag(info);
|
||||
setItemInfo(info);
|
||||
applyLoadingState(promiseStateChanged);
|
||||
applyDotState(info, false /* animate */);
|
||||
setDownloadStateContentDescription(info, info.getProgressLevel());
|
||||
@@ -290,7 +325,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
applyIconAndLabel(info);
|
||||
|
||||
// We don't need to check the info since it's not a WorkspaceItemInfo
|
||||
super.setTag(info);
|
||||
setItemInfo(info);
|
||||
|
||||
|
||||
// Verify high res immediately
|
||||
verifyHighRes();
|
||||
@@ -309,7 +345,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
public void applyFromItemInfoWithIcon(ItemInfoWithIcon info) {
|
||||
applyIconAndLabel(info);
|
||||
// We don't need to check the info since it's not a WorkspaceItemInfo
|
||||
super.setTag(info);
|
||||
setItemInfo(info);
|
||||
|
||||
// Verify high res immediately
|
||||
verifyHighRes();
|
||||
@@ -317,18 +353,22 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
setDownloadStateContentDescription(info, info.getProgressLevel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply label and tag using a {@link SearchActionItemInfo}
|
||||
*/
|
||||
@UiThread
|
||||
public void applyFromSearchActionItemInfo(SearchActionItemInfo searchActionItemInfo) {
|
||||
applyIconAndLabel(searchActionItemInfo);
|
||||
setTag(searchActionItemInfo);
|
||||
private void setItemInfo(ItemInfoWithIcon itemInfo) {
|
||||
setTag(itemInfo);
|
||||
if (mBubbleTextHolder != null) {
|
||||
mBubbleTextHolder.onItemInfoUpdated(itemInfo);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBubbleTextHolder(
|
||||
BubbleTextHolder bubbleTextHolder) {
|
||||
mBubbleTextHolder = bubbleTextHolder;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
protected void applyIconAndLabel(ItemInfoWithIcon info) {
|
||||
boolean useTheme = mDisplay == DISPLAY_WORKSPACE || mDisplay == DISPLAY_FOLDER;
|
||||
boolean useTheme = mDisplay == DISPLAY_WORKSPACE || mDisplay == DISPLAY_FOLDER
|
||||
|| mDisplay == DISPLAY_TASKBAR;
|
||||
FastBitmapDrawable iconDrawable = info.newIcon(getContext(), useTheme);
|
||||
mDotParams.color = IconPalette.getMutedColor(iconDrawable.getIconColor(), 0.54f);
|
||||
|
||||
@@ -395,6 +435,10 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
* Returns true if the touch down at the provided position be ignored
|
||||
*/
|
||||
protected boolean shouldIgnoreTouchDown(float x, float y) {
|
||||
if (mDisplay == DISPLAY_TASKBAR) {
|
||||
// Allow touching within padding on taskbar, given icon sizes are smaller.
|
||||
return false;
|
||||
}
|
||||
return y < getPaddingTop()
|
||||
|| x < getPaddingLeft()
|
||||
|| y > getHeight() - getPaddingBottom()
|
||||
@@ -414,7 +458,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
}
|
||||
|
||||
void clearPressedBackground() {
|
||||
public void clearPressedBackground() {
|
||||
setPressed(false);
|
||||
setStayPressed(false);
|
||||
}
|
||||
@@ -431,6 +475,75 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
checkForEllipsis();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
|
||||
super.onTextChanged(text, start, lengthBefore, lengthAfter);
|
||||
checkForEllipsis();
|
||||
}
|
||||
|
||||
private void checkForEllipsis() {
|
||||
if (!ENABLE_ICON_LABEL_AUTO_SCALING.get()) {
|
||||
return;
|
||||
}
|
||||
float width = getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();
|
||||
if (width <= 0) {
|
||||
return;
|
||||
}
|
||||
setLetterSpacing(0);
|
||||
|
||||
String text = getText().toString();
|
||||
TextPaint paint = getPaint();
|
||||
if (paint.measureText(text) < width) {
|
||||
return;
|
||||
}
|
||||
|
||||
float spacing = findBestSpacingValue(paint, text, width, MIN_LETTER_SPACING);
|
||||
// Reset the paint value so that the call to TextView does appropriate diff.
|
||||
paint.setLetterSpacing(0);
|
||||
setLetterSpacing(spacing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the appropriate text spacing to display the provided text
|
||||
* @param paint the paint used by the text view
|
||||
* @param text the text to display
|
||||
* @param allowedWidthPx available space to render the text
|
||||
* @param minSpacingEm minimum spacing allowed between characters
|
||||
* @return the final textSpacing value
|
||||
*
|
||||
* @see #setLetterSpacing(float)
|
||||
*/
|
||||
private float findBestSpacingValue(TextPaint paint, String text, float allowedWidthPx,
|
||||
float minSpacingEm) {
|
||||
paint.setLetterSpacing(minSpacingEm);
|
||||
if (paint.measureText(text) > allowedWidthPx) {
|
||||
// If there is no result at high limit, we can do anything more
|
||||
return minSpacingEm;
|
||||
}
|
||||
|
||||
float lowLimit = 0;
|
||||
float highLimit = minSpacingEm;
|
||||
|
||||
for (int i = 0; i < MAX_SEARCH_LOOP_COUNT; i++) {
|
||||
float value = (lowLimit + highLimit) / 2;
|
||||
paint.setLetterSpacing(value);
|
||||
if (paint.measureText(text) < allowedWidthPx) {
|
||||
highLimit = value;
|
||||
} else {
|
||||
lowLimit = value;
|
||||
}
|
||||
}
|
||||
|
||||
// At the end error on the higher side
|
||||
return highLimit;
|
||||
}
|
||||
|
||||
@SuppressWarnings("wrongcall")
|
||||
protected void drawWithoutDot(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
@@ -478,19 +591,29 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
return mDotInfo != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the icon bounds on the view depending on the layout type.
|
||||
*/
|
||||
public void getIconBounds(Rect outBounds) {
|
||||
getIconBounds(this, outBounds, mIconSize);
|
||||
getIconBounds(mIconSize, outBounds);
|
||||
}
|
||||
|
||||
public static void getIconBounds(View iconView, Rect outBounds, int iconSize) {
|
||||
int top = iconView.getPaddingTop();
|
||||
int left = (iconView.getWidth() - iconSize) / 2;
|
||||
int right = left + iconSize;
|
||||
int bottom = top + iconSize;
|
||||
outBounds.set(left, top, right, bottom);
|
||||
/**
|
||||
* Get the icon bounds on the view depending on the layout type.
|
||||
*/
|
||||
public void getIconBounds(int iconSize, Rect outBounds) {
|
||||
Utilities.setRectToViewCenter(this, iconSize, outBounds);
|
||||
if (mLayoutHorizontal) {
|
||||
if (mIsRtl) {
|
||||
outBounds.offsetTo(getWidth() - iconSize - getPaddingRight(), outBounds.top);
|
||||
} else {
|
||||
outBounds.offsetTo(getPaddingLeft(), outBounds.top);
|
||||
}
|
||||
} else {
|
||||
outBounds.offsetTo(outBounds.left, getPaddingTop());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets whether to vertically center the content.
|
||||
*/
|
||||
@@ -675,8 +798,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
itemInfo.contentDescription));
|
||||
} else if (hasDot()) {
|
||||
int count = mDotInfo.getNotificationCount();
|
||||
setContentDescription(getContext().getResources().getQuantityString(
|
||||
R.plurals.dotted_app_label, count, itemInfo.contentDescription, count));
|
||||
setContentDescription(
|
||||
getAppLabelPluralString(itemInfo.contentDescription.toString(), count));
|
||||
} else {
|
||||
setContentDescription(itemInfo.contentDescription);
|
||||
}
|
||||
@@ -776,7 +899,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
} else if (info instanceof PackageItemInfo) {
|
||||
applyFromItemInfoWithIcon((PackageItemInfo) info);
|
||||
} else if (info instanceof SearchActionItemInfo) {
|
||||
applyFromSearchActionItemInfo((SearchActionItemInfo) info);
|
||||
applyFromItemInfoWithIcon((SearchActionItemInfo) info);
|
||||
}
|
||||
|
||||
mDisableRelayout = false;
|
||||
@@ -806,8 +929,11 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
|
||||
private void updateTranslation() {
|
||||
super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x);
|
||||
super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y);
|
||||
super.setTranslationX(mTranslationForReorderBounce.x + mTranslationForReorderPreview.x
|
||||
+ mTranslationForMoveFromCenterAnimation.x
|
||||
+ mTranslationXForTaskbarAlignmentAnimation);
|
||||
super.setTranslationY(mTranslationForReorderBounce.y + mTranslationForReorderPreview.y
|
||||
+ mTranslationForMoveFromCenterAnimation.y);
|
||||
}
|
||||
|
||||
public void setReorderBounceOffset(float x, float y) {
|
||||
@@ -840,6 +966,29 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
return mScaleForReorderBounce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets translation values for move from center animation
|
||||
*/
|
||||
public void setTranslationForMoveFromCenterAnimation(float x, float y) {
|
||||
mTranslationForMoveFromCenterAnimation.set(x, y);
|
||||
updateTranslation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets translationX for taskbar to launcher alignment animation
|
||||
*/
|
||||
public void setTranslationXForTaskbarAlignmentAnimation(float translationX) {
|
||||
mTranslationXForTaskbarAlignmentAnimation = translationX;
|
||||
updateTranslation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns translationX value for taskbar to launcher alignment animation
|
||||
*/
|
||||
public float getTranslationXForTaskbarAlignmentAnimation() {
|
||||
return mTranslationXForTaskbarAlignmentAnimation;
|
||||
}
|
||||
|
||||
public View getView() {
|
||||
return this;
|
||||
}
|
||||
@@ -851,8 +1000,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
|
||||
@Override
|
||||
public void getWorkspaceVisualDragBounds(Rect bounds) {
|
||||
DeviceProfile grid = mActivity.getDeviceProfile();
|
||||
BubbleTextView.getIconBounds(this, bounds, grid.iconSizePx);
|
||||
getIconBounds(mIconSize, bounds);
|
||||
}
|
||||
|
||||
private int getIconSizeForDisplay(int display) {
|
||||
@@ -860,15 +1008,16 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
switch (display) {
|
||||
case DISPLAY_ALL_APPS:
|
||||
return grid.allAppsIconSizePx;
|
||||
case DISPLAY_WORKSPACE:
|
||||
case DISPLAY_FOLDER:
|
||||
return grid.folderChildIconSizePx;
|
||||
case DISPLAY_WORKSPACE:
|
||||
default:
|
||||
return grid.iconSizePx;
|
||||
}
|
||||
}
|
||||
|
||||
public void getSourceVisualDragBounds(Rect bounds) {
|
||||
BubbleTextView.getIconBounds(this, bounds, getIconSizeForDisplay(mDisplay));
|
||||
getIconBounds(mIconSize, bounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -891,4 +1040,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
setCompoundDrawables(null, newIcon, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
private String getAppLabelPluralString(String appName, int notificationCount) {
|
||||
MessageFormat icuCountFormat = new MessageFormat(
|
||||
getResources().getString(R.string.dotted_app_label),
|
||||
Locale.getDefault());
|
||||
HashMap<String, Object> args = new HashMap();
|
||||
args.put("app_name", appName);
|
||||
args.put("count", notificationCount);
|
||||
return icuCountFormat.format(args);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user