[关闭]
@act262 2017-03-17T08:01:01.000000Z 字数 2784 阅读 1590

ImageView使用tint属性

Android


Android中颜色值对应的也是一个Drawable,其实现类是ColorDrawable,ColorDrawable中对应的了多状态的颜色ColorStateList即color目录下的selector.

API 21+,使用的是ColorStateList存储状态颜色,在Drawable不同状态下使用对应的颜色更新ColorFilter去着色

  1. public ImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes){
  2. if (a.hasValue(R.styleable.ImageView_tint)) {
  3. mDrawableTintList = a.getColorStateList(R.styleable.ImageView_tint);
  4. mHasDrawableTint = true;
  5. // Prior to L, this attribute would always set a color filter with
  6. // blending mode SRC_ATOP. Preserve that default behavior.
  7. mDrawableTintMode = PorterDuff.Mode.SRC_ATOP;
  8. mHasDrawableTintMode = true;
  9. }
  10. if (a.hasValue(R.styleable.ImageView_tintMode)) {
  11. mDrawableTintMode = Drawable.parseTintMode(a.getInt(
  12. R.styleable.ImageView_tintMode, -1), mDrawableTintMode);
  13. mHasDrawableTintMode = true;
  14. }
  15. applyImageTint();
  16. }
  17. // 更新着色 -> BitmapDrawable.setTintList -> Drawable.updateTintFilter
  18. private void applyImageTint() {
  19. if (mDrawable != null && (mHasDrawableTint || mHasDrawableTintMode)) {
  20. mDrawable = mDrawable.mutate();
  21. if (mHasDrawableTint) {
  22. mDrawable.setTintList(mDrawableTintList);
  23. }
  24. if (mHasDrawableTintMode) {
  25. mDrawable.setTintMode(mDrawableTintMode);
  26. }
  27. // The drawable (or one of its children) may not have been
  28. // stateful before applying the tint, so let's try again.
  29. if (mDrawable.isStateful()) {
  30. mDrawable.setState(getDrawableState());
  31. }
  32. }
  33. }

API 19,使用的是单一的颜色值,直接通过设置ColorFilter直接着色

  1. // ImageView构造函数
  2. int tint = a.getInt(com.android.internal.R.styleable.ImageView_tint, 0);
  3. if (tint != 0) {
  4. setColorFilter(tint);
  5. }
  6. //...
  7. // 相当于设置tint
  8. public final void setColorFilter(int color, PorterDuff.Mode mode) {
  9. setColorFilter(new PorterDuffColorFilter(color, mode));
  10. }

所以API21以前不能在xml中使用ColorStateList的颜色,只能指定单一的颜色值.
res/color/text_color

  1. <selector xmlns:android="http://schemas.android.com/apk/res/android">
  2. <item android:color="#d2b978" android:state_pressed="true" />
  3. <item android:color="#b4b9c3" />
  4. </selector>

ImageView布局:

  1. <!-- API 21 以下只支持单色 -->
  2. <ImageView
  3. android:layout_width="wrap_content"
  4. android:layout_height="wrap_content"
  5. android:tint="#f00"
  6. android:src="@mipmap/ic_search" />
  7. <!-- tint 使用多状态颜色(ColorStateList),API<21 不支持,会Crash -->
  8. <ImageView
  9. android:layout_width="wrap_content"
  10. android:layout_height="wrap_content"
  11. android:tint="@color/text_color"
  12. android:src="@mipmap/ic_search" />

为了兼容版本可以使用java代码动态设置

  1. // 不同状态下着色的颜色color
  2. ColorStateList colorStateList = ContextCompat.getColorStateList(getContext(), R.color.text_color);
  3. // 对应color state
  4. int[][] states = new int[][]{new int[]{android.R.attr.state_pressed}, new int[]{}};
  5. StateListDrawable stateListDrawable = new StateListDrawable();
  6. Drawable drawable = ContextCompat.getDrawable(getContext(), R.mipmap.ic_search);
  7. stateListDrawable.addState(states[0], drawable);
  8. stateListDrawable.addState(states[1], drawable);
  9. Drawable wrap = DrawableCompat.wrap(stateListDrawable);
  10. DrawableCompat.setTintList(wrap, colorStateList);
  11. ImageView imageView = (ImageView) view.findViewById(R.id.image);
  12. imageView.setImageDrawable(wrap);
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注