Merge branch 'android15-release' into merge-aosp15
This commit is contained in:
@@ -21,6 +21,13 @@ package com.android.launcher3;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V2;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_ICON_LABEL_AUTO_SCALING;
|
||||
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
|
||||
import static android.text.Layout.Alignment.ALIGN_NORMAL;
|
||||
|
||||
import static com.android.launcher3.Flags.enableCursorHoverStates;
|
||||
import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_NO_BADGE;
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_SKIP_USER_BADGE;
|
||||
import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
|
||||
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INCREMENTAL_DOWNLOAD_ACTIVE;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
|
||||
@@ -38,11 +45,13 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.icu.text.MessageFormat;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextUtils.TruncateAt;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Property;
|
||||
import android.util.Size;
|
||||
import android.util.TypedValue;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
@@ -55,7 +64,6 @@ import androidx.annotation.UiThread;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dot.DotInfo;
|
||||
import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
@@ -67,13 +75,13 @@ import com.android.launcher3.icons.DotRenderer;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.icons.PlaceHolderIconDrawable;
|
||||
import com.android.launcher3.icons.cache.HandlerRunnable;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.popup.PopupContainerWithArrow;
|
||||
import com.android.launcher3.search.StringMatcherUtility;
|
||||
import com.android.launcher3.util.CancellableTask;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.MultiTranslateDelegate;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
@@ -99,10 +107,10 @@ import app.lawnchair.util.LawnchairUtilsKt;
|
||||
public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
IconLabelDotView, DraggableView, Reorderable {
|
||||
|
||||
private static final int DISPLAY_WORKSPACE = 0;
|
||||
public static final int DISPLAY_WORKSPACE = 0;
|
||||
public static final int DISPLAY_ALL_APPS = 1;
|
||||
private static final int DISPLAY_FOLDER = 2;
|
||||
protected static final int DISPLAY_TASKBAR = 5;
|
||||
public static final int DISPLAY_FOLDER = 2;
|
||||
public static final int DISPLAY_TASKBAR = 5;
|
||||
public static final int DISPLAY_SEARCH_RESULT = 6;
|
||||
public static final int DISPLAY_SEARCH_RESULT_SMALL = 7;
|
||||
public static final int DISPLAY_PREDICTION_ROW = 8;
|
||||
@@ -152,6 +160,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
private final MultiTranslateDelegate mTranslateDelegate = new MultiTranslateDelegate(this);
|
||||
private final ActivityContext mActivity;
|
||||
private FastBitmapDrawable mIcon;
|
||||
private DeviceProfile mDeviceProfile;
|
||||
private boolean mCenterVertically;
|
||||
|
||||
protected int mDisplay;
|
||||
@@ -165,6 +174,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private boolean mHideBadge = false;
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private boolean mSkipUserBadge = false;
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private boolean mIsIconVisible = true;
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private int mTextColor;
|
||||
@@ -176,11 +187,30 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private DotInfo mDotInfo;
|
||||
private DotRenderer mDotRenderer;
|
||||
private Locale mCurrentLocale;
|
||||
@ViewDebug.ExportedProperty(category = "launcher", deepExport = true)
|
||||
protected DotRenderer.DrawParams mDotParams;
|
||||
private Animator mDotScaleAnim;
|
||||
private boolean mForceHideDot;
|
||||
|
||||
// These fields, related to showing running apps, are only used for Taskbar.
|
||||
private final Size mRunningAppIndicatorSize;
|
||||
private final int mRunningAppIndicatorTopMargin;
|
||||
private final Size mMinimizedAppIndicatorSize;
|
||||
private final int mMinimizedAppIndicatorTopMargin;
|
||||
private final Paint mRunningAppIndicatorPaint;
|
||||
private final Rect mRunningAppIconBounds = new Rect();
|
||||
private RunningAppState mRunningAppState;
|
||||
|
||||
/**
|
||||
* Various options for the running state of an app.
|
||||
*/
|
||||
public enum RunningAppState {
|
||||
NOT_RUNNING,
|
||||
RUNNING,
|
||||
MINIMIZED,
|
||||
}
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private boolean mStayPressed;
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
@@ -188,7 +218,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private boolean mDisableRelayout = false;
|
||||
|
||||
private HandlerRunnable mIconLoadRequest;
|
||||
private CancellableTask mIconLoadRequest;
|
||||
|
||||
private boolean mEnableIconUpdateAnimation = false;
|
||||
|
||||
@@ -203,20 +233,22 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mActivity = ActivityContext.lookupContext(context);
|
||||
FastBitmapDrawable.setFlagHoverEnabled(enableCursorHoverStates());
|
||||
|
||||
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();
|
||||
mDeviceProfile = mActivity.getDeviceProfile();
|
||||
mCenterVertically = a.getBoolean(R.styleable.BubbleTextView_centerVertically, false);
|
||||
|
||||
mDisplay = a.getInteger(R.styleable.BubbleTextView_iconDisplay, DISPLAY_WORKSPACE);
|
||||
final int defaultIconSize;
|
||||
if (mDisplay == DISPLAY_WORKSPACE) {
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
|
||||
setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
|
||||
defaultIconSize = grid.iconSizePx;
|
||||
setCenterVertically(grid.iconCenterVertically);
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, mDeviceProfile.iconTextSizePx);
|
||||
setCompoundDrawablePadding(mDeviceProfile.iconDrawablePaddingPx);
|
||||
defaultIconSize = mDeviceProfile.iconSizePx;
|
||||
setCenterVertically(mDeviceProfile.iconCenterVertically);
|
||||
} else if (mDisplay == DISPLAY_ALL_APPS || mDisplay == DISPLAY_PREDICTION_ROW
|
||||
|| mDisplay == DISPLAY_SEARCH_RESULT_APP_ROW) {
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
|
||||
@@ -224,33 +256,47 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
defaultIconSize = grid.allAppsIconSizePx;
|
||||
LawnchairUtilsKt.overrideAllAppsTextColor(this);
|
||||
} else if (mDisplay == DISPLAY_FOLDER) {
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.folderChildTextSizePx);
|
||||
setCompoundDrawablePadding(grid.folderChildDrawablePaddingPx);
|
||||
defaultIconSize = grid.folderChildIconSizePx;
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, mDeviceProfile.folderChildTextSizePx);
|
||||
setCompoundDrawablePadding(mDeviceProfile.folderChildDrawablePaddingPx);
|
||||
defaultIconSize = mDeviceProfile.folderChildIconSizePx;
|
||||
} else if (mDisplay == DISPLAY_SEARCH_RESULT) {
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_PX, mDeviceProfile.allAppsIconTextSizePx);
|
||||
defaultIconSize = getResources().getDimensionPixelSize(R.dimen.search_row_icon_size);
|
||||
} else if (mDisplay == DISPLAY_SEARCH_RESULT_SMALL) {
|
||||
defaultIconSize = getResources().getDimensionPixelSize(
|
||||
R.dimen.search_row_small_icon_size);
|
||||
} else if (mDisplay == DISPLAY_TASKBAR) {
|
||||
defaultIconSize = grid.iconSizePx;
|
||||
defaultIconSize = mDeviceProfile.taskbarIconSize;
|
||||
} else {
|
||||
// widget_selection or shortcut_popup
|
||||
defaultIconSize = grid.iconSizePx;
|
||||
defaultIconSize = mDeviceProfile.iconSizePx;
|
||||
}
|
||||
FontManager.INSTANCE.get(context).overrideFont(this, attrs);
|
||||
|
||||
mCenterVertically = a.getBoolean(R.styleable.BubbleTextView_centerVertically, false);
|
||||
|
||||
mIconSize = a.getDimensionPixelSize(R.styleable.BubbleTextView_iconSizeOverride,
|
||||
defaultIconSize);
|
||||
a.recycle();
|
||||
|
||||
mRunningAppIndicatorSize = new Size(
|
||||
getResources().getDimensionPixelSize(R.dimen.taskbar_running_app_indicator_width),
|
||||
getResources().getDimensionPixelSize(R.dimen.taskbar_running_app_indicator_height));
|
||||
mMinimizedAppIndicatorSize = new Size(
|
||||
getResources().getDimensionPixelSize(R.dimen.taskbar_minimized_app_indicator_width),
|
||||
getResources().getDimensionPixelSize(
|
||||
R.dimen.taskbar_minimized_app_indicator_height));
|
||||
mRunningAppIndicatorTopMargin = getResources().getDimensionPixelSize(
|
||||
R.dimen.taskbar_running_app_indicator_top_margin);
|
||||
mMinimizedAppIndicatorTopMargin = getResources().getDimensionPixelSize(
|
||||
R.dimen.taskbar_minimized_app_indicator_top_margin);
|
||||
mRunningAppIndicatorPaint = new Paint();
|
||||
mRunningAppIndicatorPaint.setColor(getResources().getColor(
|
||||
R.color.taskbar_running_app_indicator_color, context.getTheme()));
|
||||
|
||||
mLongPressHelper = new CheckLongPressHelper(this);
|
||||
|
||||
mDotParams = new DotRenderer.DrawParams();
|
||||
|
||||
mCurrentLocale = context.getResources().getConfiguration().locale;
|
||||
setEllipsize(TruncateAt.END);
|
||||
setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
|
||||
setTextAlpha(1f);
|
||||
@@ -268,6 +314,10 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
mHideBadge = hideBadge;
|
||||
}
|
||||
|
||||
public void setSkipUserBadge(boolean skipUserBadge) {
|
||||
mSkipUserBadge = skipUserBadge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the view so it can be recycled.
|
||||
*/
|
||||
@@ -289,6 +339,13 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
mIconLoadRequest.cancel();
|
||||
mIconLoadRequest = null;
|
||||
}
|
||||
// Reset any shifty arrangements in case animation is disrupted.
|
||||
setPivotY(0);
|
||||
setAlpha(1);
|
||||
setScaleY(1);
|
||||
setTranslationY(0);
|
||||
setMaxLines(1);
|
||||
setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
private void cancelDotScaleAnim() {
|
||||
@@ -297,7 +354,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
}
|
||||
|
||||
private void animateDotScale(float... dotScales) {
|
||||
public void animateDotScale(float... dotScales) {
|
||||
cancelDotScaleAnim();
|
||||
mDotScaleAnim = ObjectAnimator.ofFloat(this, DOT_SCALE_PROPERTY, dotScales);
|
||||
mDotScaleAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@@ -385,10 +442,17 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
setDownloadStateContentDescription(info, info.getProgressLevel());
|
||||
}
|
||||
|
||||
/** Updates whether the app this view represents is currently running. */
|
||||
@UiThread
|
||||
public void updateRunningState(RunningAppState runningAppState) {
|
||||
mRunningAppState = runningAppState;
|
||||
}
|
||||
|
||||
protected void setItemInfo(ItemInfoWithIcon itemInfo) {
|
||||
setTag(itemInfo);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@UiThread
|
||||
protected void applyIconAndLabel(ItemInfoWithIcon info) {
|
||||
boolean useTheme = shouldUseTheme();
|
||||
@@ -407,17 +471,17 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
|
||||
/**
|
||||
* Only if actual text can be displayed in two line, the {@code true} value will be effective.
|
||||
* Only if actual text can be displayed in two line, the {@code true} value will
|
||||
* be effective.
|
||||
*/
|
||||
protected boolean shouldUseTwoLine() {
|
||||
return (FeatureFlags.twoLineAllApps(this.getContext()) && mDisplay == DISPLAY_ALL_APPS)
|
||||
return (FeatureFlags.twoLineAllApps(this.getContext()) && mDisplay == DISPLAY_ALL_APPS)
|
||||
|| (FeatureFlags.ENABLE_TWOLINE_DEVICESEARCH.get()
|
||||
&& mDisplay == DISPLAY_SEARCH_RESULT);
|
||||
&& mDisplay == DISPLAY_SEARCH_RESULT);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@VisibleForTesting
|
||||
public void applyLabel(ItemInfoWithIcon info) {
|
||||
public void applyLabel(ItemInfo info) {
|
||||
CharSequence label = info.title;
|
||||
if (label != null) {
|
||||
mLastOriginalText = label;
|
||||
@@ -542,9 +606,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
|
||||
private void checkForEllipsis() {
|
||||
if (!ENABLE_ICON_LABEL_AUTO_SCALING.get()) {
|
||||
return;
|
||||
}
|
||||
float width = getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight();
|
||||
if (width <= 0) {
|
||||
return;
|
||||
@@ -565,13 +626,12 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
|
||||
/**
|
||||
* 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,
|
||||
@@ -608,6 +668,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
public void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
drawDotIfNecessary(canvas);
|
||||
drawRunningAppIndicatorIfNecessary(canvas);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -619,7 +680,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
if (!mForceHideDot && (hasDot() || mDotParams.scale > 0)) {
|
||||
getIconBounds(mDotParams.iconBounds);
|
||||
Utilities.scaleRectAboutCenter(mDotParams.iconBounds,
|
||||
IconShape.getNormalizationScale());
|
||||
IconShape.INSTANCE.get(getContext()).getNormalizationScale());
|
||||
final int scrollX = getScrollX();
|
||||
final int scrollY = getScrollY();
|
||||
canvas.translate(scrollX, scrollY);
|
||||
@@ -628,6 +689,25 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a line under the app icon if this is representing a running app in
|
||||
* Desktop Mode.
|
||||
*/
|
||||
protected void drawRunningAppIndicatorIfNecessary(Canvas canvas) {
|
||||
if (mRunningAppState == RunningAppState.NOT_RUNNING || mDisplay != DISPLAY_TASKBAR) {
|
||||
return;
|
||||
}
|
||||
getIconBounds(mRunningAppIconBounds);
|
||||
// TODO(b/333872717): update color, shape, and size of indicator
|
||||
boolean isMinimized = mRunningAppState == RunningAppState.MINIMIZED;
|
||||
int indicatorTop = mRunningAppIconBounds.bottom + (isMinimized ? mMinimizedAppIndicatorTopMargin
|
||||
: mRunningAppIndicatorTopMargin);
|
||||
final Size indicatorSize = isMinimized ? mMinimizedAppIndicatorSize : mRunningAppIndicatorSize;
|
||||
canvas.drawRect(mRunningAppIconBounds.centerX() - indicatorSize.getWidth() / 2,
|
||||
indicatorTop, mRunningAppIconBounds.centerX() + indicatorSize.getWidth() / 2,
|
||||
indicatorTop + indicatorSize.getHeight(), mRunningAppIndicatorPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceHideDot(boolean forceHideDot) {
|
||||
if (mForceHideDot == forceHideDot) {
|
||||
@@ -647,7 +727,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
return mForceHideDot;
|
||||
}
|
||||
|
||||
private boolean hasDot() {
|
||||
public boolean hasDot() {
|
||||
return mDotInfo != null;
|
||||
}
|
||||
|
||||
@@ -696,21 +776,28 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
if (mCenterVertically) {
|
||||
Paint.FontMetrics fm = getPaint().getFontMetrics();
|
||||
int cellHeightPx = mIconSize + getCompoundDrawablePadding() +
|
||||
(int) Math.ceil(fm.bottom - fm.top);
|
||||
int height = MeasureSpec.getSize(heightMeasureSpec);
|
||||
setPadding(getPaddingLeft(), (height - cellHeightPx) / 2, getPaddingRight(),
|
||||
getPaddingBottom());
|
||||
}
|
||||
// Only apply two line for all_apps and device search only if necessary.
|
||||
if (shouldUseTwoLine() && (mLastOriginalText != null)) {
|
||||
int allowedVerticalSpace = height - getPaddingTop() - getPaddingBottom()
|
||||
- mDeviceProfile.allAppsIconSizePx
|
||||
- mDeviceProfile.allAppsIconDrawablePaddingPx;
|
||||
CharSequence modifiedString = modifyTitleToSupportMultiLine(
|
||||
MeasureSpec.getSize(widthMeasureSpec) - getCompoundPaddingLeft()
|
||||
- getCompoundPaddingRight(),
|
||||
allowedVerticalSpace,
|
||||
mLastOriginalText,
|
||||
getPaint(), mBreakPointsIntArray);
|
||||
getPaint(),
|
||||
mBreakPointsIntArray,
|
||||
getLineSpacingMultiplier(),
|
||||
getLineSpacingExtra());
|
||||
if (!TextUtils.equals(modifiedString, mLastModifiedText)) {
|
||||
mLastModifiedText = modifiedString;
|
||||
setText(modifiedString);
|
||||
@@ -795,7 +882,10 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
* new string is by
|
||||
* iterating through the list of break points and determining if the strings
|
||||
* between the break
|
||||
* points can fit within the line it is in.
|
||||
* points can fit within the line it is in. We will show the modified string if
|
||||
* there is enough
|
||||
* horizontal and vertical space, otherwise this method will just return the
|
||||
* original string.
|
||||
* Example assuming each character takes up one spot:
|
||||
* title = "Battery Stats", breakpoint = [6], stringPtr = 0, limitedWidth = 7
|
||||
* We get the current word -> from sublist(0, breakpoint[i]+1) so sublist (0,7)
|
||||
@@ -808,8 +898,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
* would be
|
||||
* "Battery\nStats"
|
||||
*/
|
||||
public static CharSequence modifyTitleToSupportMultiLine(int limitedWidth, CharSequence title,
|
||||
TextPaint paint, IntArray breakPoints) {
|
||||
public static CharSequence modifyTitleToSupportMultiLine(int limitedWidth, int limitedHeight,
|
||||
CharSequence title, TextPaint paint, IntArray breakPoints, float spacingMultiplier,
|
||||
float spacingExtra) {
|
||||
// current title is less than the width allowed so we can just skip
|
||||
if (title == null || paint.measureText(title, 0, title.length()) <= limitedWidth) {
|
||||
return title;
|
||||
@@ -817,6 +908,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
float currentWordWidth, runningWidth = 0;
|
||||
CharSequence currentWord;
|
||||
StringBuilder newString = new StringBuilder();
|
||||
paint.setLetterSpacing(MIN_LETTER_SPACING);
|
||||
int stringPtr = 0;
|
||||
for (int i = 0; i < breakPoints.size() + 1; i++) {
|
||||
if (i < breakPoints.size()) {
|
||||
@@ -830,11 +922,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
if (runningWidth <= limitedWidth) {
|
||||
newString.append(currentWord);
|
||||
} else {
|
||||
// there is no more space
|
||||
if (i == 0) {
|
||||
// if the first words exceeds width, just return as the first line will ellipse
|
||||
return title;
|
||||
} else {
|
||||
if (i != 0) {
|
||||
// If putting word onto a new line, make sure there is no space or new line
|
||||
// character in the beginning of the current word and just put in the rest of
|
||||
// the characters.
|
||||
@@ -847,8 +935,14 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
: EMPTY;
|
||||
}
|
||||
newString.append(NEW_LINE).append(lastCharacters);
|
||||
return newString.toString();
|
||||
StaticLayout staticLayout = new StaticLayout(newString, paint, limitedWidth,
|
||||
ALIGN_NORMAL, spacingMultiplier, spacingExtra, false);
|
||||
if (staticLayout.getHeight() < limitedHeight) {
|
||||
return newString.toString();
|
||||
}
|
||||
}
|
||||
// if the first words exceeds width, just return as the first line will ellipse
|
||||
return title;
|
||||
}
|
||||
if (i >= breakPoints.size()) {
|
||||
// no need to look forward into the string if we've already finished processing
|
||||
@@ -880,7 +974,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
if ((info.runtimeStatusFlags & FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0
|
||||
|| info.hasPromiseIconUi()
|
||||
|| (info.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0
|
||||
|| (ENABLE_DOWNLOAD_APP_UX_V2.get() && icon != null)) {
|
||||
|| (icon != null)) {
|
||||
updateProgressBarUi(info.getProgressLevel() == 100 ? icon : null);
|
||||
}
|
||||
}
|
||||
@@ -897,7 +991,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
/** Applies the given progress level to the this icon's progress bar. */
|
||||
@Nullable
|
||||
public PreloadIconDrawable applyProgressLevel() {
|
||||
if (!(getTag() instanceof ItemInfoWithIcon)) {
|
||||
if (!(getTag() instanceof ItemInfoWithIcon)
|
||||
|| ((ItemInfoWithIcon) getTag()).isInactiveArchive()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -918,9 +1013,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
if (mIcon instanceof PreloadIconDrawable) {
|
||||
preloadIconDrawable = (PreloadIconDrawable) mIcon;
|
||||
preloadIconDrawable.setLevel(progressLevel);
|
||||
preloadIconDrawable.setIsDisabled(ENABLE_DOWNLOAD_APP_UX_V2.get()
|
||||
? info.getProgressLevel() == 0
|
||||
: !info.isAppStartable());
|
||||
preloadIconDrawable.setIsDisabled(isIconDisabled(info));
|
||||
} else {
|
||||
preloadIconDrawable = makePreloadIcon();
|
||||
setIcon(preloadIconDrawable);
|
||||
@@ -946,12 +1039,19 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
final PreloadIconDrawable preloadDrawable = newPendingIcon(getContext(), info);
|
||||
|
||||
preloadDrawable.setLevel(progressLevel);
|
||||
preloadDrawable.setIsDisabled(ENABLE_DOWNLOAD_APP_UX_V2.get()
|
||||
? info.getProgressLevel() == 0
|
||||
: !info.isAppStartable());
|
||||
preloadDrawable.setIsDisabled(isIconDisabled(info));
|
||||
return preloadDrawable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true to grey the icon if the icon is either suspended or if the icon
|
||||
* is pending
|
||||
* download
|
||||
*/
|
||||
public boolean isIconDisabled(ItemInfoWithIcon info) {
|
||||
return info.isDisabled() || info.isPendingDownload();
|
||||
}
|
||||
|
||||
public void applyDotState(ItemInfo itemInfo, boolean animate) {
|
||||
if (mIcon instanceof FastBitmapDrawable) {
|
||||
boolean wasDotted = mDotInfo != null;
|
||||
@@ -989,7 +1089,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
}
|
||||
|
||||
private void setDownloadStateContentDescription(ItemInfoWithIcon info, int progressLevel) {
|
||||
if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
|
||||
if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_ARCHIVED) != 0 && progressLevel == 0) {
|
||||
setContentDescription(getContext().getString(R.string.app_archived_title, info.title));
|
||||
} else if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
|
||||
String percentageString = NumberFormat.getPercentInstance()
|
||||
.format(progressLevel * 0.01);
|
||||
if ((info.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) {
|
||||
@@ -1212,4 +1314,13 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
|
||||
public boolean canShowLongPressPopup() {
|
||||
return getTag() instanceof ItemInfo && ShortcutUtil.supportsShortcuts((ItemInfo) getTag());
|
||||
}
|
||||
|
||||
/** Returns the package name of the app this icon represents. */
|
||||
public String getTargetPackageName() {
|
||||
Object tag = getTag();
|
||||
if (tag instanceof ItemInfo itemInfo) {
|
||||
return itemInfo.getTargetPackage();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user