From 127dfe1255ae6edc57d53fdc6e2ca32308ac28da Mon Sep 17 00:00:00 2001 From: afohrman Date: Fri, 16 Jun 2017 11:24:56 -0400 Subject: [PATCH] Add graceful degradation for character counter and label text overflow color. Previously, the character counter and label overflow color ended up as Color.MAGENTA, which actually is a sickly pink color. This appears to have been happening when the theme doesn't extend from Theme.Design, and therefore doesn't have textErrorColor. On API 23 and above, it gets set to MAGENTA instead of throwing an exception. The only reason this pink color was being used for the character counter and not the error text is because there already a fix for the error text - it just wasn't applied to the character counter. I pulled the logic for the fix out to make this graceful degradation code reusable for both error and character text, and for future situations like this. PiperOrigin-RevId: 159229718 --- .../design/widget/TextInputLayout.java | 74 +++++++++---------- .../design/widget/TextInputLayoutTest.java | 1 - 2 files changed, 36 insertions(+), 39 deletions(-) diff --git a/lib/src/android/support/design/widget/TextInputLayout.java b/lib/src/android/support/design/widget/TextInputLayout.java index 1387524c2..3a8fb0dc3 100644 --- a/lib/src/android/support/design/widget/TextInputLayout.java +++ b/lib/src/android/support/design/widget/TextInputLayout.java @@ -33,6 +33,8 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.DrawableContainer; import android.os.Build; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import android.os.Parcel; import android.os.Parcelable; import android.support.annotation.DrawableRes; @@ -127,7 +129,7 @@ public class TextInputLayout extends LinearLayout { private static final String LOG_TAG = "TextInputLayout"; private final FrameLayout mInputFrame; - private @Nullable Animator mErrorAnimator; + @Nullable private Animator mErrorAnimator; EditText mEditText; private final float mErrorTextTranslationYPx; @@ -622,30 +624,7 @@ public class TextInputLayout extends LinearLayout { if (mTypeface != null) { mErrorView.setTypeface(mTypeface); } - boolean useDefaultColor = false; - try { - TextViewCompat.setTextAppearance(mErrorView, mErrorTextAppearance); - - if (Build.VERSION.SDK_INT >= 23 - && mErrorView.getTextColors().getDefaultColor() == Color.MAGENTA) { - // Caused by our theme not extending from Theme.Design*. On API 23 and - // above, unresolved theme attrs result in MAGENTA rather than an exception. - // Flag so that we use a decent default - useDefaultColor = true; - } - } catch (Exception e) { - // Caused by our theme not extending from Theme.Design*. Flag so that we use - // a decent default - useDefaultColor = true; - } - if (useDefaultColor) { - // Probably caused by our theme not extending from Theme.Design*. Instead - // we manually set something appropriate - TextViewCompat.setTextAppearance( - mErrorView, android.support.v7.appcompat.R.style.TextAppearance_AppCompat_Caption); - mErrorView.setTextColor( - ContextCompat.getColor(getContext(), R.color.design_textinput_error_color_light)); - } + setTextAppearanceCompatWithErrorFallback(mErrorView, mErrorTextAppearance); mErrorView.setVisibility(INVISIBLE); ViewCompat.setAccessibilityLiveRegion( mErrorView, ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE); @@ -804,16 +783,7 @@ public class TextInputLayout extends LinearLayout { mCounterView.setTypeface(mTypeface); } mCounterView.setMaxLines(1); - try { - TextViewCompat.setTextAppearance(mCounterView, mCounterTextAppearance); - } catch (Exception e) { - // Probably caused by our theme not extending from Theme.Design*. Instead - // we manually set something appropriate - TextViewCompat.setTextAppearance( - mCounterView, android.support.v7.appcompat.R.style.TextAppearance_AppCompat_Caption); - mCounterView.setTextColor( - ContextCompat.getColor(getContext(), R.color.design_textinput_error_color_light)); - } + setTextAppearanceCompatWithErrorFallback(mCounterView, mCounterTextAppearance); addIndicator(mCounterView, -1); if (mEditText == null) { updateCounter(0); @@ -893,7 +863,7 @@ public class TextInputLayout extends LinearLayout { } else { mCounterOverflowed = length > mCounterMaxLength; if (wasCounterOverflowed != mCounterOverflowed) { - TextViewCompat.setTextAppearance( + setTextAppearanceCompatWithErrorFallback( mCounterView, mCounterOverflowed ? mCounterOverflowTextAppearance : mCounterTextAppearance); } @@ -906,6 +876,34 @@ public class TextInputLayout extends LinearLayout { } } + private void setTextAppearanceCompatWithErrorFallback( + TextView textView, @StyleRes int textAppearance) { + boolean useDefaultColor = false; + try { + TextViewCompat.setTextAppearance(textView, textAppearance); + + if (VERSION.SDK_INT >= VERSION_CODES.M + && textView.getTextColors().getDefaultColor() == Color.MAGENTA) { + // Caused by our theme not extending from Theme.Design*. On API 23 and + // above, unresolved theme attrs result in MAGENTA rather than an exception. + // Flag so that we use a decent default + useDefaultColor = true; + } + } catch (Exception e) { + // Caused by our theme not extending from Theme.Design*. Flag so that we use + // a decent default + useDefaultColor = true; + } + if (useDefaultColor) { + // Probably caused by our theme not extending from Theme.Design*. Instead + // we manually set something appropriate + TextViewCompat.setTextAppearance( + textView, android.support.v7.appcompat.R.style.TextAppearance_AppCompat_Caption); + textView.setTextColor( + ContextCompat.getColor(getContext(), R.color.design_textinput_error_color_light)); + } + } + private void updateEditTextBackground() { if (mEditText == null) { return; @@ -1290,7 +1288,7 @@ public class TextInputLayout extends LinearLayout { } /** - * Applies a tint to the the password visibility toggle drawable. Does not modify the current tint + * Applies a tint to the password visibility toggle drawable. Does not modify the current tint * mode, which is {@link PorterDuff.Mode#SRC_IN} by default. * *

Subsequent calls to {@link #setPasswordVisibilityToggleDrawable(Drawable)} will @@ -1385,7 +1383,7 @@ public class TextInputLayout extends LinearLayout { r, rect.bottom - mEditText.getCompoundPaddingBottom()); - // Set the collapsed bounds to be the the full height (minus padding) to match the + // Set the collapsed bounds to be the full height (minus padding) to match the // EditText's editable area mCollapsingTextHelper.setCollapsedBounds( l, getPaddingTop(), r, bottom - top - getPaddingBottom()); diff --git a/tests/javatests/android/support/design/widget/TextInputLayoutTest.java b/tests/javatests/android/support/design/widget/TextInputLayoutTest.java index 99dd1ebfa..ffcafd0af 100644 --- a/tests/javatests/android/support/design/widget/TextInputLayoutTest.java +++ b/tests/javatests/android/support/design/widget/TextInputLayoutTest.java @@ -295,7 +295,6 @@ public class TextInputLayoutTest { assertEquals(INPUT_TEXT, info.hintText); } - /** Regression test for b/31663756. */ @UiThreadTest @Test public void testDrawableStateChanged() {