Android AppCompat 23.1.0着色化合物可拉伸
我使用了下面的方法,使用android.support.design 23.0.1对复合绘图板进行适当着色。现在他们发布了23.1.0,它在api LVL16上不再工作了,我所有的绘图工具都是黑色的 有人有什么建议吗Android AppCompat 23.1.0着色化合物可拉伸,android,android-support-library,android-drawable,android-support-design,Android,Android Support Library,Android Drawable,Android Support Design,我使用了下面的方法,使用android.support.design 23.0.1对复合绘图板进行适当着色。现在他们发布了23.1.0,它在api LVL16上不再工作了,我所有的绘图工具都是黑色的 有人有什么建议吗 private void setCompoundColor(TextView view) { Drawable drawable = view.getCompoundDrawables()[0]; Drawable wrap = DrawableCompat.w
private void setCompoundColor(TextView view) {
Drawable drawable = view.getCompoundDrawables()[0];
Drawable wrap = DrawableCompat.wrap(drawable);
DrawableCompat.setTint(wrap, ContextCompat.getColor(this, R.color.primaryLighter2));
DrawableCompat.setTintMode(wrap, PorterDuff.Mode.SRC_IN);
wrap = wrap.mutate();
view.setCompoundDrawablesRelativeWithIntrinsicBounds(wrap, null, null, null);
}
谢谢。上周我遇到了同样的问题,结果在AppCompatTextView v23.1.0中,复合绘图自动着色 这是我找到的解决方案,下面将详细说明我为什么这么做。它不是很干净,但至少它能让你给你的复合拖布上色 解决方案 将此代码放入助手类或自定义文本视图/按钮中:
/**
* 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();
}
}
然后可以调用removedefaulttining(this)扩展AppCompatTextView或AppCompatButton的类的每个构造函数上的代码>。例如:
public MyCustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
removeDefaultTinting(this);
}
这样,使用v23.0.1的代码应该可以在v23.1.0上运行
我不满意使用反射来更改AppCompat库中的属性,但这是我发现的在v23.1.0的复合绘图表上使用着色的唯一方法。希望有人能找到更好的解决方案,或者在AppCompat公共方法中添加复合可绘制着色
更新
我发现了另一个更简单的解决方案:只有在使用xml设置复合绘图表时,才会出现此错误。不要在xml中设置它们,然后在代码中设置它们,它就会工作。构造函数中的错误代码,在调用它之后设置可绘制项不受影响
解释
在AppCompatTextView构造函数中,初始化文本帮助程序:
mTextHelper.loadFromAttributes(attrs, defStyleAttr);
mTextHelper.applyCompoundDrawablesTints();
在TextHelperloadFromAttributes
函数中,为每个复合绘图表创建一个着色列表。如您所见,mdrawablexxtint.mHasTintList
始终设置为truemdrawablexxtint.mTintList
是将应用的着色颜色,仅从AppCompat的硬编码值中获取。对于自定义绘图,它将始终为空。因此,最终得到的色调具有空的“色调列表”
问题在于,此色调应用于构造函数中,每次设置或更改可绘制对象时:
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if (mBackgroundTintHelper != null) {
mBackgroundTintHelper.applySupportBackgroundTint();
}
if (mTextHelper != null) {
mTextHelper.applyCompoundDrawablesTints();
}
}
因此,如果您对复合绘图表应用着色,然后调用超级方法,如view.setCompoundDrawablesRelativeWithIntrinsicBounds
,文本帮助程序将对您的绘图表应用其空着色,删除您所做的一切
最后,这里是应用色调的函数:
final void applyCompoundDrawableTint(Drawable drawable, TintInfo info) {
if (drawable != null && info != null) {
TintManager.tintDrawable(drawable, info, mView.getDrawableState());
}
}
参数中的tintintinfo
是texthelper类的mdrawablexxtint
属性。如您所见,如果为null,则不应用任何着色。将所有可绘制的着色属性设置为null可防止AppCompat应用其着色,并使您可以对可绘制的内容执行任何操作
我没有找到一个干净的方法来阻止这种行为,或者让它涂上我想要的颜色。所有属性都是私有的,没有getter。您可以尝试这样的方法
ContextCompat.getDrawable(context, R.drawable.cool_icon)?.apply {
setTint(ContextCompat.getColor(context, R.color.red))
}
哇!不是我想得到的那种回答!我将尝试你的解决方案,但这种解决方案对Android来说是一种耻辱。。。你认为打开一个bug让谷歌检查是明智的吗?非常感谢:)不客气!我花了半天的时间使用调试器来理解为什么我的绘图是白色的,所以当我看到你的问题时,我觉得有必要创建一个帐户并发布我的发现:)打开一个bug可能是个好主意,我只是没有花时间。这是一个临时解决方案,下次修改AppCompat时可能会停止工作。他们用来着色复合绘图表的代码并不太长或复杂,只是可以从外部类完全访问。一个简单的设置器,用于每个复合可拉丝的色调,并且它是固定的…针对该问题完成。从昨天开始,我发现这个库在某些设备上也破坏了TransitionDrawable:)AppCompatAutoCompleteTextView不存在mTextHelper?使用不将它们放入xml的方法可以完美地工作!检查更新。Philippe David的代码可以工作,但根据我的经验,您应该编写wrap=wrap.mutate()代码>在DrawableCompat.setTint()之前。否则,它将无法正常工作,因为原始可拉丝将被修改。
ContextCompat.getDrawable(context, R.drawable.cool_icon)?.apply {
setTint(ContextCompat.getColor(context, R.color.red))
}