| Index: chrome/android/java/src/org/chromium/chrome/browser/snackbar/TemplatePreservingTextView.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/TemplatePreservingTextView.java b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/TemplatePreservingTextView.java
|
| index 36f4759d422ccde16430d13b43f0edeb6704d5bd..480670fc181d80be72a7ddffc4c4920a477aee7f 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/TemplatePreservingTextView.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/TemplatePreservingTextView.java
|
| @@ -13,13 +13,21 @@ import android.util.AttributeSet;
|
| import android.widget.TextView;
|
|
|
| /**
|
| - * A {@link AppCompatTextView} that properly clips content within a template, instead of clipping
|
| - * the templated content.
|
| + * A {@link AppCompatTextView} that truncates content within a template, instead of truncating
|
| + * the template text. Truncation only happens if maxLines is set to 1 and there's not enough space
|
| + * to display the entire content.
|
| + *
|
| + * For example, given the following template and content
|
| + * Template: "%s was closed"
|
| + * Content: "https://www.google.com/webhp?sourceid=chrome-instant&q=potato"
|
| + *
|
| + * the TemplatePreservingTextView would truncate the content but not the template text:
|
| + * "https://www.google.com/webh... was closed"
|
| */
|
| public class TemplatePreservingTextView extends AppCompatTextView {
|
| - private static final String DEFAULT_TEMPLATE = "%1$s";
|
| private String mTemplate;
|
| - private CharSequence mContent;
|
| + private CharSequence mContent = "";
|
| + private CharSequence mVisibleText;
|
|
|
| /**
|
| * Builds an instance of an {@link TemplatePreservingTextView}.
|
| @@ -31,41 +39,38 @@ public class TemplatePreservingTextView extends AppCompatTextView {
|
| }
|
|
|
| /**
|
| - * Update template for undo text
|
| - * @param template Template format string (eg. "Close %s")
|
| + * Sets the template format string. setText() must be called after calling this method for the
|
| + * new template text to take effect.
|
| + *
|
| + * @param template Template format string (e.g. "Closed %s"), or null. If null is passed, this
|
| + * view acts like a normal TextView.
|
| */
|
| public void setTemplate(String template) {
|
| - mTemplate = TextUtils.isEmpty(template) ? DEFAULT_TEMPLATE : template;
|
| + mTemplate = TextUtils.isEmpty(template) ? null : template;
|
| }
|
|
|
| /**
|
| * This will take {@code text} and apply it to the internal template, building a new
|
| - * {@link String} to set. This {code text} will be automatically truncated to fit within
|
| + * {@link String} to set. This {@code text} will be automatically truncated to fit within
|
| * the template as best as possible, making sure the template does not get clipped.
|
| */
|
| @Override
|
| public void setText(CharSequence text, BufferType type) {
|
| - final int availWidth = getWidth() - getPaddingLeft() - getPaddingRight();
|
| - setClippedText(text, availWidth);
|
| + mContent = text != null ? text : "";
|
| + setContentDescription(mTemplate == null ? mContent : String.format(mTemplate, mContent));
|
| + updateVisibleText(0, true);
|
| }
|
|
|
| @Override
|
| protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
| final int availWidth =
|
| MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
|
| - setClippedText(mContent, availWidth);
|
| -
|
| + updateVisibleText(availWidth,
|
| + MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.UNSPECIFIED);
|
| super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
| }
|
|
|
| - private void setClippedText(CharSequence text, int availWidth) {
|
| - mContent = text != null ? text : "";
|
| -
|
| - if (mTemplate == null) {
|
| - super.setText(mContent, BufferType.SPANNABLE);
|
| - return;
|
| - }
|
| -
|
| + private CharSequence getTruncatedText(int availWidth) {
|
| final TextPaint paint = getPaint();
|
|
|
| // Calculate the width the template takes.
|
| @@ -79,13 +84,25 @@ public class TemplatePreservingTextView extends AppCompatTextView {
|
| CharSequence clipped = TextUtils.ellipsize(mContent, paint, contentWidth, TruncateAt.END);
|
|
|
| // Build the full string, which should fit within availWidth.
|
| - String finalContent = String.format(mTemplate, clipped);
|
| + return String.format(mTemplate, clipped);
|
| + }
|
| +
|
| + private void updateVisibleText(int availWidth, boolean unspecifiedWidth) {
|
| + CharSequence visibleText;
|
| + if (mTemplate == null) {
|
| + visibleText = mContent;
|
| + } else if (getMaxLines() != 1 || unspecifiedWidth) {
|
| + visibleText = String.format(mTemplate, mContent);
|
| + } else {
|
| + visibleText = getTruncatedText(availWidth);
|
| + }
|
|
|
| - // BufferType.SPANNABLE is required so that TextView.getIterableTextForAccessibility()
|
| - // doesn't call our custom setText(). See crbug.com/449311
|
| - super.setText(finalContent, BufferType.SPANNABLE);
|
| + if (!visibleText.equals(mVisibleText)) {
|
| + mVisibleText = visibleText;
|
|
|
| - // Set the content description to the non-ellipsized text
|
| - setContentDescription(String.format(mTemplate, mContent));
|
| + // BufferType.SPANNABLE is required so that TextView.getIterableTextForAccessibility()
|
| + // doesn't call our custom setText(). See crbug.com/449311
|
| + super.setText(mVisibleText, BufferType.SPANNABLE);
|
| + }
|
| }
|
| }
|
|
|