Ich hatte das gleiche Problem letzte Woche, und es stellt sich heraus in der AppCompatTextView v23.1.0, zusammengesetzte Zeichen werden automatisch getönt.
Hier ist die Lösung, die ich gefunden habe, mit mehr Erklärungen, warum ich das unten getan habe. Es ist nicht sehr sauber, aber zumindest können Sie Ihre zusammengesetzten Zeichen tönen!
SOLUTION
Diesen Code in einer Hilfsklasse oder in Ihrer benutzerdefinierten Textview/Button:
/**
* The app compat text view automatically sets the compound drawable tints for a static array of drawables ids.
* If the drawable id is not in the list, the lib apply a null tint, removing the custom tint set before.
* There is no way to change this (private attributes/classes, only set in the constructor...)
*
* @param object the object on which to disable default tinting.
*/
public static void removeDefaultTinting(Object object) {
try {
// Get the text helper field.
Field mTextHelperField = object.getClass().getSuperclass().getDeclaredField("mTextHelper");
mTextHelperField.setAccessible(true);
// Get the text helper object instance.
final Object mTextHelper = mTextHelperField.get(object);
if (mTextHelper != null) {
// Apply tint to all private attributes. See AppCompat source code for usage of theses attributes.
setObjectFieldToNull(mTextHelper, "mDrawableStartTint");
setObjectFieldToNull(mTextHelper, "mDrawableEndTint");
setObjectFieldToNull(mTextHelper, "mDrawableLeftTint");
setObjectFieldToNull(mTextHelper, "mDrawableTopTint");
setObjectFieldToNull(mTextHelper, "mDrawableRightTint");
setObjectFieldToNull(mTextHelper, "mDrawableBottomTint");
}
} catch (NoSuchFieldException e) {
// If it doesn't work, we can do nothing else. The icons will be white, we will see it.
e.printStackTrace();
} catch (IllegalAccessException e) {
// If it doesn't work, we can do nothing else. The icons will be white, we will see it.
e.printStackTrace();
}
}
/**
* Set the field of an object to null.
*
* @param object the TextHelper object (class is not accessible...).
* @param fieldName the name of the tint field.
*/
private static void setObjectFieldToNull(Object object, String fieldName) {
try {
Field tintField;
// Try to get field from class or super class (depends on the implementation).
try {
tintField = object.getClass().getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
tintField = object.getClass().getSuperclass().getDeclaredField(fieldName);
}
tintField.setAccessible(true);
tintField.set(object, null);
} catch (NoSuchFieldException e) {
// If it doesn't work, we can do nothing else. The icons will be white, we will see it.
e.printStackTrace();
} catch (IllegalAccessException e) {
// If it doesn't work, we can do nothing else. The icons will be white, we will see it.
e.printStackTrace();
}
}
Dann Sie removeDefaultTinting(this);
auf jedem Konstruktor Ihrer Klasse erweitern AppCompatTextView oder AppCompatButton aufrufen können. Zum Beispiel:
public MyCustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
removeDefaultTinting(this);
}
Mit diesem Code mit v23.0.1 arbeiten sollte auf v23.1.0 arbeiten.
Ich bin nicht zufrieden mit der Verwendung von Reflexion, um Attribute in der AppCompat-Bibliothek zu ändern, aber dies ist die einzige Möglichkeit, Tönung auf Compound-Zeichen mit v23.1.0 zu verwenden. Hoffentlich wird jemand eine bessere Lösung finden, oder Compound Drawable Tönung wird den öffentlichen AppCompat-Methoden hinzugefügt.
UPDATE
fand ich eine andere einfachere Lösung: Dieser Fehler tritt nur auf, wenn Sie Verbindung Drawables mit xml gesetzt. Setzen Sie sie nicht in XML, und setzen Sie sie in Ihrem Code und es wird funktionieren. Der fehlerhafte Code, der sich im Konstruktor befindet, wird nicht beeinflusst, wenn Sie Zeichnungsobjekte festlegen, nachdem sie aufgerufen wurden.
Explikationen
In AppCompatTextView Konstruktor, ein Text-Helfer initialisiert wird:
mTextHelper.loadFromAttributes(attrs, defStyleAttr);
mTextHelper.applyCompoundDrawablesTints();
In der TextHelper loadFromAttributes
Funktion wird eine Tönung Liste für jede Verbindung ziehbar erstellt. Wie Sie sehen können, ist mDrawableXXXTint.mHasTintList
immer auf True eingestellt. mDrawableXXXTint.mTintList
ist die Farbtonfarbe, die angewendet wird und nur von fest codierten Werten von AppCompat abgerufen wird. Für Ihre benutzerdefinierten Zeichen ist es immer Null. Sie haben also eine Tönung mit einer Null-Tint-Liste.
TypedArray a = context.obtainStyledAttributes(attrs, VIEW_ATTRS, defStyleAttr, 0);
final int ap = a.getResourceId(0, -1);
// Now read the compound drawable and grab any tints
if (a.hasValue(1)) {
mDrawableLeftTint = new TintInfo();
mDrawableLeftTint.mHasTintList = true;
mDrawableLeftTint.mTintList = tintManager.getTintList(a.getResourceId(1, 0));
}
if (a.hasValue(2)) {
mDrawableTopTint = new TintInfo();
mDrawableTopTint.mHasTintList = true;
mDrawableTopTint.mTintList = tintManager.getTintList(a.getResourceId(2, 0));
}
...
Das Problem ist, dass diese Färbung im Konstruktor angelegt wird, und jedes Mal, wenn ein ziehbar eingestellt oder geändert wird:
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if (mBackgroundTintHelper != null) {
mBackgroundTintHelper.applySupportBackgroundTint();
}
if (mTextHelper != null) {
mTextHelper.applyCompoundDrawablesTints();
}
}
Wenn Sie also eine Tönung zu einer Verbindung ziehbar anwenden, und dann rufen eine super Methode wie view.setCompoundDrawablesRelativeWithIntrinsicBounds
, der Text-Helper wird seinen Null-Farbton auf Ihre Zeichen anwenden, alles entfernen, was Sie getan haben ...
Schließlich ist hier die Funktion des Farbtons Anwendung:
final void applyCompoundDrawableTint(Drawable drawable, TintInfo info) {
if (drawable != null && info != null) {
TintManager.tintDrawable(drawable, info, mView.getDrawableState());
}
}
Die TintInfo
in Parameter ist die mDrawableXXXTint
Attribut der texthelper Klasse. Wie Sie sehen können, wird kein Farbton angewendet, wenn es null ist. Wenn Sie alle Attribute für die Zeichnungsfarbe auf null setzen, wird verhindert, dass AppCompat den Farbton anwendet, und Sie können die gewünschten Einstellungen für die Zeichnungsobjekte vornehmen.
Ich habe keine saubere Möglichkeit gefunden, dieses Verhalten zu blockieren oder die gewünschte Farbe aufzutragen. Alle Attribute sind privat, ohne Getter.
Überprüfen Sie [diese Antwort] (http://StackOverflow.com/a/35867517/2826147) für die Aktualisierung. –
Der Code von Philippe David funktioniert, aber aus meiner Erfahrung sollten Sie 'wrap = wrap.mutate();' vor 'DrawableCompat.setTint()' schreiben. Andernfalls wird es nicht ordnungsgemäß funktionieren, da das ursprüngliche Zeichen geändert wird. – marius