ColorFilter

转载请注明出处:

平时在Android开发中,一般不太可能频繁使用到Paint——画笔。但是在某些特殊的情况下,例如 自定义控件(继承View)的时候,有时候就需要请出画笔在画布(Canvas,将下篇文章中讲述Canvas)上像“画”出我们想要的元素。然而,很多开发人员对画笔Paint的了解知之甚少,包括我自己在内,所以在今天在这里总结一下Paint的在Android图像处理中起到的作用和用法。

Paint的简单了解

同样,我们学习Paint之前,首先查看一下Paint类的API,其中,我们最需要关注的地方就是Paint类给我们提供了很多的setter方法,可以通过调用setter方法来设置自己的偏好。下面是在Android Studio中查到的Paint类的部分setter:

好,可以看到Paint对外提供的方法还是非常丰富的,下面挑几个经常使用到的介绍一下:

Paint(int flags):构建Paint实例,常用的flags是ANTI_ALIAS_FLAG,消除锯齿。

set(Paint src):将另一个Paint复制给当前Paint实例,不多说了。

setAntiAlias(boolean aa):是否消除锯齿。

setColor(int color):设置画笔的颜色。

setColorFilter(ColorFilterfilter):设置色彩过滤器,很重要,后面还会有一些总结。

setStrokeWidth(float width):设置Paint划线的宽度。

setStyle(Paint.Stylestyle):设置Paint的风格。画笔样式分三种:

1.Paint.Style.STROKE:描边 。2.Paint.Style.FILL_AND_STROKE:描边并填充 。3.Paint.Style.FILL:填充 。

setXfermode(Xfermodexfermode):设置Paint的模式,后面有详细点的说明,很重要。

下面,我们来自定义一个View来尝试一下使用Paint:

public class CustomView1 extends View {private Paint mPaint;private Context mContext;public CustomView1(Context context) {this(context,null);}public CustomView1(Context context, AttributeSet attrs) {super(context, attrs);mContext = context;initPaint();}private void initPaint() {//初始化Paint,并且设置消除锯齿。mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);/***设置画笔样式为描边* 画笔样式分三种:* 1.Paint.Style.STROKE:描边* 2.Paint.Style.FILL_AND_STROKE:描边并填充* 3.Paint.Style.FILL:填充*/mPaint.setStyle(Paint.Style.FILL);//设置描边的粗细,单位:像素px 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素mPaint.setStrokeWidth(20);//设置画笔颜色为自定义颜色mPaint.setColor(Color.argb(255,255,128,102));}@Overrideprotected void onDraw(Canvas canvas) {//画一个圆形,取屏幕中心点为圆心canvas.drawCircle(ScreenUtil.getScreenW(mContext)/2,ScreenUtil.getScreenH(mContext)/2,100,mPaint);}}好了,以上就是绘制一个圆形的简单代码,我们在布局文件中引用一下这个自定义控件,运行一下。

效果如上,一个很圆很圆的圆形啊,等等,貌似看着有点像岛国的旗子,好吧!待会就换了它。

ColorFilter

上面说过了,我们将会这里介绍一下setColorFilter(ColorFilter filter)的用法。setColorFilter(ColorFilter filter)内接收一个参数ColorFilter,在Android Studio中点击进去看一下源码,可以看到ColorFilter里的代码量很少:

public class ColorFilter {/*** Holds the pointer to the native SkColorFilter instance.** @hide*/public long native_instance;@Overrideprotected void finalize() throws Throwable {try {super.finalize();} finally {destroyFilter(native_instance);}}static native void destroyFilter(long native_instance);}由此根据我们的经验,判断ColorFilter可能是个父类,具体实现可能下面还有子类完成的,于是再看Google的文档:

一目了然了,ColorFilter下有3个子类ColorMatrixColorFilter, LightingColorFilter, PorterDuffColorFilter ,下面逐一学习一下。

ColorMatrixColorFilter

ColorMatrixColorFilter翻译为颜色矩阵过滤器,神马是颜色矩阵?实际上,安卓中管理色彩矩阵是以RGBA像素点的方式加载到内存的,这些点统一使用ColorMatrix的矩阵来统一管理,矩阵定义为4*5的排列形式。那好,首先来看看ColorMatrixColorFilter的两个构造器:

public ColorMatrixColorFilter(ColorMatrix matrix) {mMatrix.set(matrix);update();}public ColorMatrixColorFilter(float[] array) {if (array.length < 20) {throw new ArrayIndexOutOfBoundsException();}mMatrix.set(array);update();}ColorMatrixColorFilter中一个构造器需要接收ColorMatrix对象,另一个需要接收一个4*5的float型数组,我们再打开Android Studio追踪一下mMatrix.set()方法,可以看到以上两个构造器里面调的set方法各自实现的方式public void set(ColorMatrix src) {System.arraycopy(src.mArray, 0, mArray, 0, 20);}public void set(float[] src) {System.arraycopy(src, 0, mArray, 0, 20);}再追踪一下System.arraycopy()方法:public static void arraycopy(float[] src, int srcPos, float[] dst, int dstPos, int length)好了,到这里,其实已经很明白了,ColorMatrixColorFilter构造器中接收的两个不同的参数,实际上底层实现方式都是一样的,都是同样调用System.arraycopy()中带float数组参数的方法。所以我们不必再考虑怎么样去写一个ColorMatrix对象传递给ColorMatrixColorFilter了,实际上我们使用第二个构造器,传递一个float数组,会显得程序更加直观易懂,那么我们就尝试写一个ColorMatrixColorFilter,并且设置给Paint吧,例子还是使用上面的那个岛国旗帜吧!public class CustomView1 extends View {private Paint mPaint;private Context mContext;public CustomView1(Context context) {this(context, null);}public CustomView1(Context context, AttributeSet attrs) {super(context, attrs);mContext = context;initPaint();}private void initPaint() {//初始化Paint,并且设置消除锯齿。mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//设置画笔样式为描边mPaint.setStyle(Paint.Style.FILL);//设置描边的粗细,单位:像素px 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素mPaint.setStrokeWidth(20);//设置画笔颜色为自定义颜色mPaint.setColor(Color.argb(255, 255, 128, 102));ColorMatrixColorFilter colorFilter = new ColorMatrixColorFilter(new float[]{1, 0, 0, 0, 0,0, 1, 0, 0, 0,0, 0, 1, 0, 0,0, 0, 0, 1, 0});mPaint.setColorFilter(colorFilter);}@Overrideprotected void onDraw(Canvas canvas) {//画一个圆形,取屏幕中心点为圆心canvas.drawCircle(ScreenUtil.getScreenW(mContext) / 2,ScreenUtil.getScreenH(mContext) / 2, 100, mPaint);}}唯有斯人面上簌簌流下的,是点点无声无行的热泪。

ColorFilter

相关文章:

你感兴趣的文章:

标签云: