Android ColorFilter and Tint

概述

关于Android ColorFilter 和 Tint之间的关系一直混淆不清。两者均是对显示的图片进行着色或者过滤。

ColorFilter: 色彩过滤

Tint: 着色

从英文原意上来讲,似乎有些相似,而从实际的效果来讲也是一致的。Android 向导文档似乎对此也是一笔带过,不愿深入,让人有些摸不着头脑:

With Android 5.0 (API level 21) and above, you can tint bitmaps and nine-patches defined as alpha masks. You can tint them with color resources or theme attributes that resolve to color sources (for example, ?android:attr/colorPrimary). Usually, you create these assets only once and color them automatically to match your theme.

You can apply a tint to BitmapDrawable or NinePatchDrawable objects with the setTint() method. You can also set the tint color and mode in your layouts with the android:tint and android:tintMode attributes.

这段文字讲述的大意是:Tint 是 API 21之后才添加的功能,可以对BitmapDrawableNinePatchDrawable 应用Tint 效果。使用tint效果可以省去我们为不同theme创建同一张图片的多个版本的麻烦。紧接着第二段讲道如何使用tint, 有两种方法:

1 调用函数:

 class Drawable {
     ...
     public void setTint (int tint);                       //Added in API 21
     public void setTintMode (PorterDuff.Mode tintMode);   //Added in API 21
     ...
}

2 XML Layout:

drawable file location: res/drawable/tintedrawable.xml

<nine-path xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/rawdrawable"
    android:tint="@color/what_ever_color"
    android:tintMode="multiply" />

layout file location: res/layout/layout_main.xml


<View
    android:id="@+id/my_view_id"
    android:layout_width="20dp"
    android:layout_height="10dp"
    android:background="@drawable/tintedrawable"/>

ImageView and Tint

class ImageView {

    public final void setColorFilter (int color, PorterDuff.Mode mode); //Added in API 1
    public void setImageTintList (ColorStateList tint);                 //Added in API 21
    public void setImageTintMode (PorterDuff.Mode tintMode);            //Added in API 21

}

除了 ImageView 可以继续使用setColorFilter(int, PorterDuff.Mode), API 21 也给ImageView 添加了setImageTintList(), setImageTintMode(), android:tint, android:tintMode 等特性!



首先我们看一个Sample, 给一个ImageView 使用这三种不同方法来着色。

        <!-- 方法一使用setColorFilter -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="setColorFilter" />

        <ImageView
            android:id="@+id/image1"
            android:layout_width="200dp"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:src="@drawable/rawdrawable"
            android:scaleType="fitXY"/>

        <!--方法二使用setImageTintList -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="setImageTintList" />

        <ImageView
            android:id="@+id/image2"
            android:layout_width="200dp"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:src="@drawable/rawdrawable"
            android:scaleType="fitXY"/>

        <!--方法三使用XML android:tint 属性 -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="android:tint" />

        <ImageView
            android:id="@+id/image3"
            android:layout_width="200dp"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:src="@drawable/rawdrawable"
            android:scaleType="fitXY"
            android:tint="#673AB7"
            android:tintMode="multiply"/>
    @Override
    public View onCreateView(LayoutInflater inflater,
         ViewGroup container, Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.tinting_fragment, null);

        mImage1 = (ImageView) v.findViewById(R.id.image1);

        mImage2 = (ImageView) v.findViewById(R.id.image2);

        updateTint( Color.argb(0xFF, 0x67, 0x3A, 0xB7),
            PorterDuff.Mode.MULTIPLY );
    }

    public void updateTint(int color, PorterDuff.Mode mode) {
        mImage1.setColorFilter(color, mode);
        mImage2.setImageTintList(ColorStateList.valueOf(color));
        mImage2.setImageTintMode(mode);
    }

从上图可以看到, 其实对于ImageView 不管采用何种方法,其最终的结果都是一样的。



我们看到ImageView.setImageTintList(ColorStateList) 实际上是接受一个ColorStateList参数,上面我们android:tint="#673AB7"的tint值是一个单一的颜色,如果改成ColorStateList那效果如何呢?

1 res/color/custom_tint.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Pressed state -->
    <item android:color="#ff0000" android:state_pressed="true" />
    <!-- Default -->
    <item android:color="#4aff48" />
</selector>

2 res/layout/layout_main.xml

 <ImageView
            android:id="@+id/image3"
            android:clickable="true"
            android:layout_width="200dp"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:src="@drawable/rawdrawable"
            android:scaleType="fitXY"
            android:tint="@color/custom_tint"
            android:tintMode="multiply"/>

当点击最下面的ImageView 的时候, 颜色并没有随着状态的改变而改变。接着我们再把ImageView 改成ImageButton:

 <ImageButton
            android:id="@+id/image3"
            android:layout_width="200dp"
            android:layout_height="50dp"
            android:layout_gravity="center_horizontal"
            android:src="@drawable/rawdrawable"
            android:scaleType="fitXY"
            android:tint="@color/custom_tint"
            android:tintMode="multiply"/>


Drawable and Tint

文档里面明确讲明了tint的引入是为了对Drawable 进行着色支持。至少对于BitmapDrawableNinePatchDrawable 文档明确指明了支持 android:tintandroid:tintMode 属性。这样的话我们对于android:tint的属性的支持就很容易从ImageView扩展到任何View, 只要将Viewandroid:background指向我们自定义的drawable:

1 res/drawable/tintedrawable.xml

<bitmap xmlns="http://schemas.android.com/apk/res/android"
    android:src="@drawable/background_image"
    android:tint="@color/custom_tint"
    android:tintMode="multiply" />

2 res/layout/layout_main.xml

 <View
            android:id="@+id/image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/tintedrawable"/>

但是和上面的问题一样,使用这种方法不支持多状态的情形。而如果我们将xml layout 中的View 改成ImageButton并且将android:background 改成android:src问题就解决了: 

 <ImageButton
            android:id="@+id/image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:src="@drawable/tintedrawable"
            android:scaleType="centerInside"/>

上面的两张图片分别是在默认状态和按下状态的ImageButton着色的效果。如果换成其他的View, 红色着色并不会出现,但是仍然会有绿色的着色效果。

通过以上的分析,发现对于tint在各个状态下自动改变着色色彩的支持仍然仅仅局限于ImageButton, 这里或许我们可以通过自定义View的方法来修正这个问题,但是如果能够做到系统原生的支持当然更好,期待读者能够提供更好的方法。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-08 09:24:43

Android ColorFilter and Tint的相关文章

android.graphics.drawable.Drawable注释翻译

/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://w

Android动画总结系列(6)——矢量图形与矢量动画

按照我一开始的打算,上面一篇文章应该是"Android动画总结系列(5)--属性动画源码分析",不过属性动画源码分析写起来还比较复杂,因为某些原因,我把精力投入到矢量动画这块了,第5篇估计会在后面一两周写完.本篇文章,我写的是Android5.0引入的新动画效果--矢量动画,初步打算后面还会加一篇源码分析. 一.概述 1.1 简述 Android应用的不断发展带来了安装包过大的尴尬,而Android之前一直都不支持矢量图形,是引起尴尬的一个重要原因.其实Android绘制界面时也是通过

ANDROID开发技术周报 ISSUE#90

新闻 [图]谷歌把电子宠物做成了Android 7.0的彩蛋:90后的回忆 Android 7.0新功能:官方或第三方应用一目了然 教程 理解Android存储系统架构 本文主要介绍跟存储相关的模块MountService和Vold的整体流程与架构设计.MountService:Android Binder服务,运行在system_server进程,用于跟Vold进行消息通信,比如MountService向Vold发送挂载SD卡的命令,或者接收到来自Vold的外设热插拔事件.Vold:全称为Vo

Android改变图片背景颜色tint(着色)或 backgroundTint

安卓对图标着色以节省apk体积,网上有很多介绍到的,使用也很简单 <ImageView     android:tint="@android:color/white"     android:backgroundTint="@android:color/black"     /> 平时都这样使用,今天得在代码中改,所以记录一下 第一种 Drawable icon; if (android.os.Build.VERSION.SDK_INT < and

Android基础入门教程——8.3.11 Paint API之—— ColorFilter(颜色过滤器)(3-3)

Android基础入门教程--8.3.11 Paint API之-- ColorFilter(颜色过滤器)(3-3) 标签(空格分隔): Android基础入门教程 本节引言: 嗯,本来说好今天不写的,还是写吧,毕竟难得空闲哈~,本节给大家带来的是 ColorFilter的第三个子类:PorterDuffColorFilter,看到PorterDuff大家一定不会 陌生吧,假如你看过前面的 Android基础入门教程--8.3.5 Paint API之-- Xfermode与PorterDuff

Android基础入门教程——8.3.10 Paint API之—— ColorFilter(颜色过滤器)(2-3)

Android基础入门教程--8.3.10 Paint API之-- ColorFilter(颜色过滤器)(2-3) 标签(空格分隔): 未分类 本节引言: 上一节中我们讲解了Android中Paint API中的ColorFilter(颜色过滤器)的第一个子类: ColorMatrixColorFilter(颜色矩阵颜色过滤器),相信又开阔了大家的Android图像处理视野, 而本节我们来研究它的第二个子类:LightingColorFilter(光照色彩颜色过滤器),先上一发 官方API文档

Android background tint颜色渲染

该篇文章主要是讲Android颜色渲染,首先先来看看PorterDuff,对绘图非常重要. PorterDuff的由来: 相信大多数人看到这个ProterDuff单词很奇怪了吧,这肿么个意思呢,然后就用有道啊,金山啊开始翻译,但是翻译软件给出的结果肯定还是 ProterDuff或者"未找到". 这是神马情况呢?因为ProterDuff是两个人名的组合: Tomas Proter和 Tom Duff. 他们是最早在SIGGRAPH上提出图形混合概念的大神级人物.有兴趣的童靴们可以自己查下

Android Paint以及ColorFilter等

我们可以通过Paint中大量的setter方法来为画笔设置属性: 这些属性大多我们都可以见名知意,很好理解,即便如此,哥还是带大家过一遍逐个剖析其用法,其中会不定穿插各种绘图类比如Canvas.Xfermode.ColorFilter等等的用法. set(Paint src) 顾名思义为当前画笔设置一个画笔,说白了就是把另一个画笔的属性设置Copy给我们的画笔,不累赘了 setARGB(int a, int r, int g, int b) 不扯了,别跟我说不懂 setAlpha(int a)

Android Paint之ColorFilter详解

尊重原创,转载请标明出处    http://blog.csdn.net/abcdef314159 在之前讲到Android Paint的使用详解的时候,其中setColorFilter(ColorFilter filter)方法没有讲,今天就来简单的分析一下,在Android中ColorFilter共有3个子类,ColorMatrixColorFilter,LightingColorFilter,PorterDuffColorFilter,今天先来看第一个ColorMatrixColorFil