@act262
2017-03-17T08:01:01.000000Z
字数 2784
阅读 2028
Android
ColorDrawable
,ColorDrawable
中对应的了多状态的颜色ColorStateList
即color目录下的selector.API 21+,使用的是ColorStateList存储状态颜色,在Drawable不同状态下使用对应的颜色更新ColorFilter去着色
public ImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes){
if (a.hasValue(R.styleable.ImageView_tint)) {
mDrawableTintList = a.getColorStateList(R.styleable.ImageView_tint);
mHasDrawableTint = true;
// Prior to L, this attribute would always set a color filter with
// blending mode SRC_ATOP. Preserve that default behavior.
mDrawableTintMode = PorterDuff.Mode.SRC_ATOP;
mHasDrawableTintMode = true;
}
if (a.hasValue(R.styleable.ImageView_tintMode)) {
mDrawableTintMode = Drawable.parseTintMode(a.getInt(
R.styleable.ImageView_tintMode, -1), mDrawableTintMode);
mHasDrawableTintMode = true;
}
applyImageTint();
}
// 更新着色 -> BitmapDrawable.setTintList -> Drawable.updateTintFilter
private void applyImageTint() {
if (mDrawable != null && (mHasDrawableTint || mHasDrawableTintMode)) {
mDrawable = mDrawable.mutate();
if (mHasDrawableTint) {
mDrawable.setTintList(mDrawableTintList);
}
if (mHasDrawableTintMode) {
mDrawable.setTintMode(mDrawableTintMode);
}
// The drawable (or one of its children) may not have been
// stateful before applying the tint, so let's try again.
if (mDrawable.isStateful()) {
mDrawable.setState(getDrawableState());
}
}
}
API 19,使用的是单一的颜色值,直接通过设置ColorFilter直接着色
// ImageView构造函数
int tint = a.getInt(com.android.internal.R.styleable.ImageView_tint, 0);
if (tint != 0) {
setColorFilter(tint);
}
//...
// 相当于设置tint
public final void setColorFilter(int color, PorterDuff.Mode mode) {
setColorFilter(new PorterDuffColorFilter(color, mode));
}
所以API21
以前不能在xml中使用ColorStateList的颜色,只能指定单一的颜色值.
res/color/text_color
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#d2b978" android:state_pressed="true" />
<item android:color="#b4b9c3" />
</selector>
ImageView布局:
<!-- API 21 以下只支持单色 -->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="#f00"
android:src="@mipmap/ic_search" />
<!-- tint 使用多状态颜色(ColorStateList),API<21 不支持,会Crash -->
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:tint="@color/text_color"
android:src="@mipmap/ic_search" />
为了兼容版本可以使用java代码动态设置
// 不同状态下着色的颜色color
ColorStateList colorStateList = ContextCompat.getColorStateList(getContext(), R.color.text_color);
// 对应color state
int[][] states = new int[][]{new int[]{android.R.attr.state_pressed}, new int[]{}};
StateListDrawable stateListDrawable = new StateListDrawable();
Drawable drawable = ContextCompat.getDrawable(getContext(), R.mipmap.ic_search);
stateListDrawable.addState(states[0], drawable);
stateListDrawable.addState(states[1], drawable);
Drawable wrap = DrawableCompat.wrap(stateListDrawable);
DrawableCompat.setTintList(wrap, colorStateList);
ImageView imageView = (ImageView) view.findViewById(R.id.image);
imageView.setImageDrawable(wrap);