From e63dd25a54e466dd250f38a424899a487304ba3d Mon Sep 17 00:00:00 2001 From: Pat Manning Date: Tue, 2 Aug 2022 16:15:29 +0100 Subject: [PATCH] Use full screen width for drop target buttons to support higher screen densities from truncating text. Scale oversized text down if after all computations it will still be truncated at higher densities. Fix: 239401464 Test: manual. To follow up with screenshot test: b/241386128 Change-Id: Ie088d0631b0d13beb2d9f9d5396a56f7b971dee1 --- res/values/dimens.xml | 1 + .../android/launcher3/ButtonDropTarget.java | 62 +++++++++++++++++-- src/com/android/launcher3/DeviceProfile.java | 2 +- src/com/android/launcher3/DropTargetBar.java | 31 ++++++---- 4 files changed, 78 insertions(+), 18 deletions(-) diff --git a/res/values/dimens.xml b/res/values/dimens.xml index a9d1127184..2e886dbd9d 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -226,6 +226,7 @@ 16sp 2dp 4dp + 20dp 8dp 16dp 8dp diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java index 3b24df2f18..5abe3d3af6 100644 --- a/src/com/android/launcher3/ButtonDropTarget.java +++ b/src/com/android/launcher3/ButtonDropTarget.java @@ -91,7 +91,7 @@ public abstract class ButtonDropTarget extends TextView Resources resources = getResources(); mDragDistanceThreshold = resources.getDimensionPixelSize(R.dimen.drag_distanceThreshold); - mDrawableSize = resources.getDimensionPixelSize(R.dimen.drop_target_text_size); + mDrawableSize = resources.getDimensionPixelSize(R.dimen.drop_target_button_drawable_size); mDrawablePadding = resources.getDimensionPixelSize( R.dimen.drop_target_button_drawable_padding); } @@ -374,11 +374,63 @@ public abstract class ButtonDropTarget extends TextView hideTooltip(); } + /** + * Returns if the text will be truncated within the provided availableWidth. + */ public boolean isTextTruncated(int availableWidth) { - availableWidth -= (getPaddingLeft() + getPaddingRight() + mDrawable.getIntrinsicWidth() - + getCompoundDrawablePadding()); - CharSequence displayedText = TextUtils.ellipsize(mText, getPaint(), availableWidth, + availableWidth -= getPaddingLeft() + getPaddingRight(); + if (mIconVisible) { + availableWidth -= mDrawable.getIntrinsicWidth() + getCompoundDrawablePadding(); + } + if (availableWidth <= 0) { + return true; + } + CharSequence firstLine = TextUtils.ellipsize(mText, getPaint(), availableWidth, TextUtils.TruncateAt.END); - return !mText.equals(displayedText); + if (!mTextMultiLine) { + return !TextUtils.equals(mText, firstLine); + } + if (TextUtils.equals(mText, firstLine)) { + // When multi-line is active, if it can display as one line, then text is not truncated. + return false; + } + CharSequence secondLine = + TextUtils.ellipsize(mText.subSequence(firstLine.length(), mText.length()), + getPaint(), availableWidth, TextUtils.TruncateAt.END); + return !(TextUtils.equals(mText.subSequence(0, firstLine.length()), firstLine) + && TextUtils.equals(mText.subSequence(firstLine.length(), secondLine.length()), + secondLine)); + } + + /** + * Reduce the size of the text until it fits the measured width or reaches a minimum. + * + * The minimum size is defined by {@code R.dimen.button_drop_target_min_text_size} and + * it diminishes by intervals defined by + * {@code R.dimen.button_drop_target_resize_text_increment} + * This functionality is very similar to the option + * {@link TextView#setAutoSizeTextTypeWithDefaults(int)} but can't be used in this view because + * the layout width is {@code WRAP_CONTENT}. + * + * @return The biggest text size in SP that makes the text fit or if the text can't fit returns + * the min available value + */ + public float resizeTextToFit() { + float minSize = Utilities.pxToSp(getResources() + .getDimensionPixelSize(R.dimen.button_drop_target_min_text_size)); + float step = Utilities.pxToSp(getResources() + .getDimensionPixelSize(R.dimen.button_drop_target_resize_text_increment)); + float textSize = Utilities.pxToSp(getTextSize()); + + int availableWidth = getMeasuredWidth(); + while (textSize > minSize) { + if (isTextTruncated(availableWidth)) { + textSize -= step; + setTextSize(textSize); + } else { + return textSize; + } + } + return minSize; } } diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 14a467ad65..55a8d370dd 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -1030,7 +1030,7 @@ public class DeviceProfile { / getCellLayoutHeight(); scale = Math.min(scale, 1f); - // Reduce scale if next pages would not be visible after scaling the workspace + // Reduce scale if next pages would not be visible after scaling the workspace. int workspaceWidth = availableWidthPx; float scaledWorkspaceWidth = workspaceWidth * scale; float maxAvailableWidth = workspaceWidth - (2 * workspaceSpringLoadedMinNextPageVisiblePx); diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java index d64cb26ff4..98ecf3a7e6 100644 --- a/src/com/android/launcher3/DropTargetBar.java +++ b/src/com/android/launcher3/DropTargetBar.java @@ -151,6 +151,8 @@ public class DropTargetBar extends FrameLayout int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST); ButtonDropTarget firstButton = mTempTargets[0]; + firstButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, + mLauncher.getDeviceProfile().dropTargetTextSizePx); firstButton.setTextVisible(true); firstButton.setIconVisible(true); firstButton.measure(widthSpec, heightSpec); @@ -160,14 +162,16 @@ public class DropTargetBar extends FrameLayout int horizontalPadding = dp.dropTargetHorizontalPaddingPx; ButtonDropTarget firstButton = mTempTargets[0]; + firstButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.dropTargetTextSizePx); firstButton.setTextVisible(true); firstButton.setIconVisible(true); firstButton.setTextMultiLine(false); - // Reset second button padding in case it was previously changed to multi-line text. + // Reset first button padding in case it was previously changed to multi-line text. firstButton.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding); ButtonDropTarget secondButton = mTempTargets[1]; + secondButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.dropTargetTextSizePx); secondButton.setTextVisible(true); secondButton.setIconVisible(true); secondButton.setTextMultiLine(false); @@ -175,20 +179,14 @@ public class DropTargetBar extends FrameLayout secondButton.setPadding(horizontalPadding, verticalPadding, horizontalPadding, verticalPadding); - float scale = dp.getWorkspaceSpringLoadScale(mLauncher); - int scaledPanelWidth = (int) (dp.getCellLayoutWidth() * scale); - int availableWidth; if (dp.isTwoPanels) { - // Both buttons for two panel fit to the width of one Cell Layout (less - // half of the center gap between the buttons). - int halfButtonGap = dp.dropTargetGapPx / 2; - availableWidth = scaledPanelWidth - halfButtonGap / 2; + // Each button for two panel fits to half the width of the screen excluding the + // center gap between the buttons. + availableWidth = (dp.availableWidthPx - dp.dropTargetGapPx) / 2; } else { - // Both buttons plus the button gap do not display past the edge of the scaled - // workspace, less a pre-defined gap from the edge of the workspace. - availableWidth = scaledPanelWidth - dp.dropTargetGapPx - - 2 * dp.dropTargetButtonWorkspaceEdgeGapPx; + // Both buttons plus the button gap do not display past the edge of the screen. + availableWidth = dp.availableWidthPx - dp.dropTargetGapPx; } int widthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST); @@ -219,6 +217,15 @@ public class DropTargetBar extends FrameLayout horizontalPadding, verticalPadding / 2); } } + + // If text is still truncated, shrink to fit in measured width and resize both targets. + float minTextSize = + Math.min(firstButton.resizeTextToFit(), secondButton.resizeTextToFit()); + if (firstButton.getTextSize() != minTextSize + || secondButton.getTextSize() != minTextSize) { + firstButton.setTextSize(minTextSize); + secondButton.setTextSize(minTextSize); + } } setMeasuredDimension(width, height); }