From: Andrei Stingaceanu Date: Fri, 26 May 2017 14:57:04 +0000 (+0100) Subject: AutoSize TextView - major fixes X-Git-Tag: android-x86-9.0-r1~1044^2~338^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=b6eaf5b8ef6cef04699a8e27f23892587f1071a0;p=android-x86%2Fframeworks-base.git AutoSize TextView - major fixes * splits the auto-size setup part from the execution function: ** in TextView CTOR we only setup and we leave the actual auto-sizing execution to happen in the view||text layout phase ** encapsulated the conditions needed to start applying auto-size in the execution function * introduces a private way to set the text size without requesting a new layout pass; auto-size always uses this practically setting the text size on the paint object and creating a new layout * calls execution autoSizeText() from within TextView#checkForRelayout() if not requestLayout() is needed => this makes sure that auto-size will be performed even if a view layout is not requested, but only a text layout * fixes the calculation of the sizes available for auto-size when configured via granularity Bug: 62050646 Bug: 38409622 Bug: 38440435 Bug: 62109627 Test: run cts --test android.widget.cts.TextViewTest -m \ CtsWidgetTestCases Test: manually tested the new behaviors in demo apps Test: new test attached in topic Change-Id: I4ccaa0a0afa3b5aa47213442d0029da2c74e7eb4 --- diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index de560920b8ca..6b328ea01997 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -1587,7 +1587,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (textColorHighlight != 0) { setHighlightColor(textColorHighlight); } - setRawTextSize(textSize); + setRawTextSize(textSize, true /* shouldRequestLayout */); setElegantTextHeight(elegant); setLetterSpacing(letterSpacing); setFontFeatureSettings(fontFeatureSettings); @@ -1757,7 +1757,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener autoSizeMinTextSizeInPx, autoSizeMaxTextSizeInPx, DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX); - setupAutoSizeText(); + if (setupAutoSizeText()) { + autoSizeText(); + invalidate(); + } break; default: throw new IllegalArgumentException( @@ -1807,7 +1810,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener validateAndSetAutoSizeTextTypeUniformConfiguration(autoSizeMinTextSizeInPx, autoSizeMaxTextSizeInPx, autoSizeStepGranularityInPx); - setupAutoSizeText(); + + if (setupAutoSizeText()) { + autoSizeText(); + invalidate(); + } } } @@ -1856,7 +1863,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } else { mHasPresetAutoSizeValues = false; } - setupAutoSizeText(); + + if (setupAutoSizeText()) { + autoSizeText(); + invalidate(); + } } } @@ -2014,20 +2025,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener : uniqueValidSizes.toArray(); } - private void setupAutoSizeText() { + private boolean setupAutoSizeText() { if (supportsAutoSizeText() && mAutoSizeTextType == AUTO_SIZE_TEXT_TYPE_UNIFORM) { // Calculate the sizes set based on minimum size, maximum size and step size if we do // not have a predefined set of sizes or if the current sizes array is empty. if (!mHasPresetAutoSizeValues || mAutoSizeTextSizesInPx.length == 0) { - // Calculate sizes to choose from based on the current auto-size configuration. - int autoSizeValuesLength = (int) Math.ceil( - (mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx) - / mAutoSizeStepGranularityInPx); - // Also reserve a slot for the max size if it fits. - if ((mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx) - % mAutoSizeStepGranularityInPx == 0) { + int autoSizeValuesLength = 1; + float currentSize = Math.round(mAutoSizeMinTextSizeInPx); + while (Math.round(currentSize + mAutoSizeStepGranularityInPx) + <= Math.round(mAutoSizeMaxTextSizeInPx)) { autoSizeValuesLength++; + currentSize += mAutoSizeStepGranularityInPx; } + int[] autoSizeTextSizesInPx = new int[autoSizeValuesLength]; float sizeToAdd = mAutoSizeMinTextSizeInPx; for (int i = 0; i < autoSizeValuesLength; i++) { @@ -2038,8 +2048,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } mNeedsAutoSizeText = true; - autoSizeText(); + } else { + mNeedsAutoSizeText = false; } + + return mNeedsAutoSizeText; } private int[] parseDimensionArray(TypedArray dimens) { @@ -3387,7 +3400,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int textSize = ta.getDimensionPixelSize(R.styleable.TextAppearance_textSize, 0); if (textSize != 0) { - setRawTextSize(textSize); + setRawTextSize(textSize, true /* shouldRequestLayout */); } final ColorStateList textColorHint = ta.getColorStateList( @@ -3612,11 +3625,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ public void setTextSize(int unit, float size) { if (!isAutoSizeEnabled()) { - setTextSizeInternal(unit, size); + setTextSizeInternal(unit, size, true /* shouldRequestLayout */); } } - private void setTextSizeInternal(int unit, float size) { + private void setTextSizeInternal(int unit, float size, boolean shouldRequestLayout) { Context c = getContext(); Resources r; @@ -3626,15 +3639,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener r = c.getResources(); } - setRawTextSize(TypedValue.applyDimension( - unit, size, r.getDisplayMetrics())); + setRawTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics()), + shouldRequestLayout); } - private void setRawTextSize(float size) { + private void setRawTextSize(float size, boolean shouldRequestLayout) { if (size != mTextPaint.getTextSize()) { mTextPaint.setTextSize(size); - if (mLayout != null) { + if (shouldRequestLayout && mLayout != null) { // Do not auto-size right after setting the text size. mNeedsAutoSizeText = false; nullLayouts(); @@ -8257,23 +8270,44 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * Automatically computes and sets the text size. */ private void autoSizeText() { - if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0) return; - final int maxWidth = getWidth() - getTotalPaddingLeft() - getTotalPaddingRight(); - final int maxHeight = getHeight() - getExtendedPaddingBottom() - getExtendedPaddingTop(); - - if (maxWidth <= 0 || maxHeight <= 0) { + if (!isAutoSizeEnabled()) { return; } - synchronized (TEMP_RECTF) { - TEMP_RECTF.setEmpty(); - TEMP_RECTF.right = maxWidth; - TEMP_RECTF.bottom = maxHeight; - final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF); - if (optimalTextSize != getTextSize()) { - setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize); + if (mNeedsAutoSizeText) { + if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0) { + return; + } + + final int availableWidth = mHorizontallyScrolling + ? VERY_WIDE + : getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight(); + final int availableHeight = getMeasuredHeight() - getExtendedPaddingBottom() + - getExtendedPaddingTop(); + + if (availableWidth <= 0 || availableHeight <= 0) { + return; + } + + synchronized (TEMP_RECTF) { + TEMP_RECTF.setEmpty(); + TEMP_RECTF.right = availableWidth; + TEMP_RECTF.bottom = availableHeight; + final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF); + + if (optimalTextSize != getTextSize()) { + setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize, + false /* shouldRequestLayout */); + + makeNewLayout(availableWidth, 0 /* hintWidth */, UNKNOWN_BORING, UNKNOWN_BORING, + mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(), + false /* bringIntoView */); + } } } + // Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing + // after the next layout pass should set this to false. + mNeedsAutoSizeText = true; } /** @@ -8315,11 +8349,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mTempTextPaint.set(getPaint()); mTempTextPaint.setTextSize(suggestedSizeInPx); - final int availableWidth = mHorizontallyScrolling - ? VERY_WIDE - : getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight(); final StaticLayout.Builder layoutBuilder = StaticLayout.Builder.obtain( - text, 0, text.length(), mTempTextPaint, availableWidth); + text, 0, text.length(), mTempTextPaint, Math.round(availableSpace.right)); layoutBuilder.setAlignment(getLayoutAlignment()) .setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier()) @@ -8469,6 +8500,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // In a fixed-height view, so use our new text layout. if (mLayoutParams.height != LayoutParams.WRAP_CONTENT && mLayoutParams.height != LayoutParams.MATCH_PARENT) { + autoSizeText(); invalidate(); return; } @@ -8477,6 +8509,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // so use our new text layout. if (mLayout.getHeight() == oldht && (mHintLayout == null || mHintLayout.getHeight() == oldht)) { + autoSizeText(); invalidate(); return; } @@ -8503,16 +8536,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mDeferScroll = -1; bringPointIntoView(Math.min(curs, mText.length())); } - - if (isAutoSizeEnabled()) { - if (mNeedsAutoSizeText) { - // Call auto-size after the width and height have been calculated. - autoSizeText(); - } - // Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing - // after the next layout round should set this to false. - mNeedsAutoSizeText = true; - } + // Call auto-size after the width and height have been calculated. + autoSizeText(); } private boolean isShowingHint() {