@act262
2017-03-17T08:01:01.000000Z
字数 2784
阅读 2223
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.updateTintFilterprivate 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);}//...// 相当于设置tintpublic 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 以下只支持单色 --><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:tint="#f00"android:src="@mipmap/ic_search" /><!-- tint 使用多状态颜色(ColorStateList),API<21 不支持,会Crash --><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:tint="@color/text_color"android:src="@mipmap/ic_search" />
为了兼容版本可以使用java代码动态设置
// 不同状态下着色的颜色colorColorStateList colorStateList = ContextCompat.getColorStateList(getContext(), R.color.text_color);// 对应color stateint[][] 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);