mirror of
https://github.com/material-components/material-components-android.git
synced 2026-02-20 08:39:55 +08:00
Merge "Workaround TextInputLayout state changes becoming permanent" into mnc-ub-dev am: 459155dd30
am: 810efa6b4f * commit '810efa6b4ffc687db1cfe717f690afe0612920d1': Workaround TextInputLayout state changes becoming permanent GitOrigin-RevId=962f72d4691edb762f658a92fb971bc559ba18e6 PiperOrigin-RevId: 140551357
This commit is contained in:
parent
3edaf2332a
commit
a366c0ffad
99
src/android/support/design/widget/DrawableUtils.java
Normal file
99
src/android/support/design/widget/DrawableUtils.java
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.support.design.widget;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.DrawableContainer;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Caution. Gross hacks ahead.
|
||||
*/
|
||||
class DrawableUtils {
|
||||
|
||||
private static final String LOG_TAG = "DrawableUtils";
|
||||
|
||||
private static Method sSetConstantStateMethod;
|
||||
private static boolean sSetConstantStateMethodFetched;
|
||||
|
||||
private static Field sDrawableContainerStateField;
|
||||
private static boolean sDrawableContainerStateFieldFetched;
|
||||
|
||||
private DrawableUtils() {}
|
||||
|
||||
static boolean setContainerConstantState(DrawableContainer drawable,
|
||||
Drawable.ConstantState constantState) {
|
||||
if (Build.VERSION.SDK_INT >= 9) {
|
||||
// We can use getDeclaredMethod() on v9+
|
||||
return setContainerConstantStateV9(drawable, constantState);
|
||||
} else {
|
||||
// Else we'll just have to set the field directly
|
||||
return setContainerConstantStateV7(drawable, constantState);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean setContainerConstantStateV9(DrawableContainer drawable,
|
||||
Drawable.ConstantState constantState) {
|
||||
if (!sSetConstantStateMethodFetched) {
|
||||
try {
|
||||
sSetConstantStateMethod = DrawableContainer.class.getDeclaredMethod(
|
||||
"setConstantState", DrawableContainer.DrawableContainerState.class);
|
||||
sSetConstantStateMethod.setAccessible(true);
|
||||
} catch (NoSuchMethodException e) {
|
||||
Log.e(LOG_TAG, "Could not fetch setConstantState(). Oh well.");
|
||||
}
|
||||
sSetConstantStateMethodFetched = true;
|
||||
}
|
||||
if (sSetConstantStateMethod != null) {
|
||||
try {
|
||||
sSetConstantStateMethod.invoke(drawable, constantState);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "Could not invoke setConstantState(). Oh well.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean setContainerConstantStateV7(DrawableContainer drawable,
|
||||
Drawable.ConstantState constantState) {
|
||||
if (!sDrawableContainerStateFieldFetched) {
|
||||
try {
|
||||
sDrawableContainerStateField = DrawableContainer.class
|
||||
.getDeclaredField("mDrawableContainerStateField");
|
||||
sDrawableContainerStateField.setAccessible(true);
|
||||
} catch (NoSuchFieldException e) {
|
||||
Log.e(LOG_TAG, "Could not fetch mDrawableContainerStateField. Oh well.");
|
||||
}
|
||||
sDrawableContainerStateFieldFetched = true;
|
||||
}
|
||||
if (sDrawableContainerStateField != null) {
|
||||
try {
|
||||
sDrawableContainerStateField.set(drawable, constantState);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "Could not set mDrawableContainerStateField. Oh well.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@ -22,7 +22,10 @@ import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.DrawableContainer;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.StyleRes;
|
||||
@ -89,6 +92,8 @@ public class TextInputLayout extends LinearLayout {
|
||||
private boolean mHintAnimationEnabled;
|
||||
private ValueAnimatorCompat mAnimator;
|
||||
|
||||
private boolean mHasReconstructedEditTextBackground;
|
||||
|
||||
public TextInputLayout(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
@ -624,17 +629,60 @@ public class TextInputLayout extends LinearLayout {
|
||||
}
|
||||
|
||||
private void updateEditTextBackground() {
|
||||
ensureBackgroundDrawableStateWorkaround();
|
||||
|
||||
final Drawable editTextBackground = mEditText.getBackground();
|
||||
if (editTextBackground == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mErrorShown && mErrorView != null) {
|
||||
// Set the EditText's background tint to the error color
|
||||
ViewCompat.setBackgroundTintList(mEditText,
|
||||
ColorStateList.valueOf(mErrorView.getCurrentTextColor()));
|
||||
// Set a color filter of the error color
|
||||
editTextBackground.setColorFilter(
|
||||
AppCompatDrawableManager.getPorterDuffColorFilter(
|
||||
mErrorView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN));
|
||||
} else if (mCounterOverflowed && mCounterView != null) {
|
||||
ViewCompat.setBackgroundTintList(mEditText,
|
||||
ColorStateList.valueOf(mCounterView.getCurrentTextColor()));
|
||||
// Set a color filter of the counter color
|
||||
editTextBackground.setColorFilter(
|
||||
AppCompatDrawableManager.getPorterDuffColorFilter(
|
||||
mCounterView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN));
|
||||
} else {
|
||||
ViewCompat.setBackgroundTintList(mEditText,
|
||||
AppCompatDrawableManager.get()
|
||||
.getTintList(getContext(), R.drawable.abc_edit_text_material));
|
||||
// Else reset the color filter and refresh the drawable state so that the
|
||||
// normal tint is used
|
||||
editTextBackground.clearColorFilter();
|
||||
mEditText.refreshDrawableState();
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureBackgroundDrawableStateWorkaround() {
|
||||
final Drawable bg = mEditText.getBackground();
|
||||
if (bg == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mHasReconstructedEditTextBackground) {
|
||||
// This is gross. There is an issue in the platform which affects container Drawables
|
||||
// where the first drawable retrieved from resources will propogate any changes
|
||||
// (like color filter) to all instances from the cache. We'll try to workaround it...
|
||||
|
||||
final Drawable newBg = bg.getConstantState().newDrawable();
|
||||
|
||||
if (bg instanceof DrawableContainer) {
|
||||
// If we have a Drawable container, we can try and set it's constant state via
|
||||
// reflection from the new Drawable
|
||||
mHasReconstructedEditTextBackground =
|
||||
DrawableUtils.setContainerConstantState(
|
||||
(DrawableContainer) bg, newBg.getConstantState());
|
||||
}
|
||||
|
||||
if (!mHasReconstructedEditTextBackground) {
|
||||
// If we reach here then we just need to set a brand new instance of the Drawable
|
||||
// as the background. This has the unfortunate side-effect of wiping out any
|
||||
// user set padding, but I'd hope that use of custom padding on an EditText
|
||||
// is limited.
|
||||
mEditText.setBackgroundDrawable(newBg);
|
||||
mHasReconstructedEditTextBackground = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user