关于ondraw你该知道的(一)

🏷️ 365bet网上娱乐网址 📅 2025-07-29 01:18:02 👤 admin 👁️ 2635 ❤️ 195
关于ondraw你该知道的(一)

目录

1.'画板'canvas

2.画布canvas的操作

0)canvas绘制前后,加入操作

1)平移

2)旋转

3)截取

4)画布的锁定

5)图层Layer合成

6)图层Layout创建和移除

3.PorterDuffXfermode

1)交集区域的16种处理及展示

2)利用PorterDuffXfermode制作圆角图

4.颜色矩阵ColorMatrix

1)原理

2)利用封装类ColorMatrix处理颜色

3)矩阵值改变原色

5.处理bitmap像素点

1.'画板'canvas

像画画一样,需要画板(canvas)和画笔(paint)

至于画板画什么,和用什么样的画笔,参考:https://blog.csdn.net/qq_37321098/article/details/84959425

安卓中用画板canvas画画,还需要传入bitmap,将bitmap和canvas绑定在一起(装载画布过程)。

(官方也不推荐使用无参方法构造canvas,需调用setBitmap函数为其设置一个Bitmap),看看源码验证一下:

//bitmap被限定非非空了

public Canvas(@NonNull Bitmap bitmap) {

if (!bitmap.isMutable()) {

throw new IllegalStateException("Immutable bitmap passed to Canvas constructor");

}

...

}

bitmap作用是用来存储所有绘制在canvas上的像素信息,所以通过这种方式创建的canvas,后面调用的Canvas.drawXX都是发生在这个bitmap上面。

换句话说:我们调用了许多Canvas.drawXX,但是其实并没有将图形直接绘制在canvas上,而是通过改变bitmap,让view重绘,从而显示改变后的bitmap。

问题:view的ondraw方法,为什么没看见bitmap绑定canvas过程?

这个系统传递给我们的canvas来自于ViewRootImpl的Surface,在绘图时系统将会SkBitmap设置到SkCanvas中并返回与之对应Canvas。所以,在onDraw()中也是有一个Bitmap的,只是这个Bitmap是由系统创建的罢了。

2.画布canvas的操作

0)canvas绘制前后,加入操作

@Override

protected void onDraw(Canvas canvas) {

//控件自身绘制前,如果是textview,则是绘制文字操作前

super.onDraw(canvas);

//控件自身绘制后,如果是textview,则是绘制文字操作后

}

1)平移

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawColor(Color.GREEN);

//初始文字

Paint paint = new Paint();

paint.setColor(Color.BLACK);

paint.setTextSize(60);

canvas.drawText("画布初始位置",100,100,paint);

//平移后画的文字

canvas.translate(100,100);

paint.setColor(Color.RED);

canvas.drawText("画布变化后位置",100,100,paint);

}

2)旋转

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawColor(Color.GREEN);

//初始文字

Paint paint = new Paint();

paint.setColor(Color.BLACK);

paint.setTextSize(60);

canvas.drawText("画布初始位置",100,100,paint);

//旋转后画的文字

canvas.rotate(15);

paint.setColor(Color.RED);

canvas.drawText("画布变化后位置",100,100,paint);

}

3)截取

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawColor(Color.GREEN);

//初始文字

Paint paint = new Paint();

paint.setColor(Color.BLACK);

paint.setTextSize(60);

canvas.drawText("画布初始位置",100,100,paint);

//裁剪后画的文字

Rect rect = new Rect(10,200,600,500);

canvas.clipRect(rect);

canvas.drawColor(Color.BLUE);

paint.setColor(Color.RED);

canvas.drawText("画布变化后位置",10,250,paint);

}

注意:

1.调用了canvas.clipRect( )后,再继续画图那么所绘的图只会在所剪裁的范围内体现

2.除了按照矩形剪裁以外,还可以有别的剪裁方式,比如:canvas.clipPath( )和canvas.clipRegion( )

4)画布的锁定

通过canvas.save锁定画布,将已经所绘的图形锁定,之后的绘图就不会影响到原来画好的图形。

之后的操作又发生在哪里呢?会生成一个新的图层(Layer),并且这个图层是透明的。此时,所有draw的方法都是在这个图层上进行,所以不会对之前画好的图形造成任何影响。

5)图层Layer合成

通过canvas.restore将canvas.save( )时会生成一个新的图层(Layer)与底下原本的画好的图像相结合形成一个新的图像。

因此,save( )和restore( )最好配对使用,若restore( )的调用次数比save( )多可能会造成异常绘制。

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

canvas.drawColor(Color.GREEN);

//初始文字

Paint paint = new Paint();

paint.setColor(Color.BLACK);

paint.setTextSize(60);

canvas.drawText("画布初始位置",100,100,paint);

canvas.save();

//save+旋转后画的图

canvas.rotate(15);

Bitmap bit= BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);

canvas.drawBitmap(bit, 100, 100, paint);

canvas.restore();

//合成后画字

paint.setColor(Color.RED);

canvas.drawText("画布变化后位置",250,250,paint);

}

绘制初始文字和图片的2个图层合成之后,canvas的旋转属性也消失了,通过最后画的文字的旋转角度可知。

6)图层Layout创建和移除

可以通过saveLayout()或者saveLayoutAlpha()去创建图层,创建的新图层遵循'先入后出'的概念,即新创建的图层永远在最上层,因此,我们画的内容也是绘制在最上层。

同样通过restore和restoreTocount()将图层出栈,出栈后,绘制的内容也是绘制在最上层的Layout图层上。

3.PorterDuffXfermode

1)交集区域的16种处理及展示

PorterDuffXfermode可以给画笔加上一些高级属性,可以设置两个图层交集区域的显示方式。

下面看看PorterDuffXfermode的16个定义常量对绘图效果的最终影响:

解释如下:

2)利用PorterDuffXfermode制作圆角图

//绘制内容

private Bitmap mBitmap;

//占位bitmap

private Bitmap mOutBitmap;

public void init() {

mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.draw_img);

mOutBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(),

Bitmap.Config.ARGB_8888);

setLayerType(View.LAYER_TYPE_SOFTWARE, null);//关掉硬件加速

}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

Paint paint = new Paint();

paint.setAntiAlias(true);

canvas.drawRoundRect(0, 0, mBitmap.getWidth(), mBitmap.getHeight(), 30, 30, paint);

//交集只显示上层

paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

canvas.drawBitmap(mBitmap,0,0,paint);

}

原图:

处理后:

4.颜色矩阵ColorMatrix

1)原理

图像描述由3部分组成:

色调(物体传播的颜色)饱和度(颜色的纯度) 由0(灰)----->100%(饱和)亮度

而在android中,系统用一个4×5的颜色矩阵ColorMatrix来处理图像。

初始颜色矩阵,不对原有的颜色值进行任何变化

分别可以通过改变系数 或者 偏移量去修改原有颜色值

2)利用封装类ColorMatrix处理颜色

a.修改色调

ColorMatrix colorMatrix1 = new ColorMatrix();

//第一个参数表示处理哪种颜色:0代表红 1绿色 2蓝色

//第二个参数表示处理的值

colorMatrix1.setRotate(0,100);

b.修改饱和度

ColorMatrix colorMatrix2 = new ColorMatrix();

//第一个参数表示处理的值

colorMatrix2.setSaturation(0);

c.修改亮度

//利用原理:三原色已相同比例混合,会显示白色

int value = 1;

ColorMatrix colorMatrix3 = new ColorMatrix();

//4个参数分别为R-G-B-A要处理的值

colorMatrix3.setScale(value,value,value,1);

d.组合a、b、c三种效果

ColorMatrix colorMatrix = new ColorMatrix();

colorMatrix.postConcat(colorMatrix1);

colorMatrix.postConcat(colorMatrix2);

colorMatrix.postConcat(colorMatrix3);

3)矩阵值改变原色

图像反转矩阵:

//绘制内容

private Bitmap mBitmap;

//占位bitmap

private Bitmap mOutBitmap;

//各种算法矩阵,可自行百度实验

//图像反转矩阵

// -1,0,0,1,1,

// 0,-1,0,1,1,

// 0,0,-1,1,1,

// 0,0,0,1,0

float value[] = {-1,0,0,1,1,0,-1,0,1,1,0,0,-1,1,1,0,0,0,1,0};

public void init() {

mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.draw_img);

mOutBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(),

Bitmap.Config.ARGB_8888);

//关掉硬件加速

setLayerType(View.LAYER_TYPE_SOFTWARE, null);

}

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//传入颜色矩阵值

android.graphics.ColorMatrix colorMa = new android.graphics.ColorMatrix();

colorMa.set(value);

//绘图

Paint paint = new Paint();

paint.setColorFilter(new ColorMatrixColorFilter(colorMa));

canvas.drawBitmap(mBitmap,0,0,paint);

}

原图:

变化后:

5.处理bitmap像素点

不会改变原图,而是拿到原图像素点,并生成新图来修改。

先拿到原图像素点,且像素点是用数组存储,函数如下:

Biamap.getPixels(int[] pixels, int offset, int stride, int x, int y, int width, int height)

参数:

pixels:接收位图颜色值的数组

offset:写入到pixels[]中的第一个像素索引值

stride:pixels[]中的行间距个数值(必须大于等于位图宽度)。不能为负数

x:从位图中读取的第一个像素的x坐标值。

y:从位图中读取的第一个像素的y坐标值

width:从每一行中读取的像素宽度

height:读取的行数

参考:https://www.cnblogs.com/fordreamxin/p/4605693.html

当我们拿到像素点数组oldPx后,还可以拿到每个像素点的RGBA值,如下:

int r=Color.red(oldPx[0]);

拿到rgba后,就可以调用一些图像处理的算法,去改变RGBA值,从而将改变后的RGBA值合成新的像素点,如下:

newPx[0]=Color.argb(a1,r1,g1,b1);

最终将新像素点数组,设置给bitmap,达到修改的目的,如下:

bitmap.setPixels(newPx,0,width,0,0,width,height);

相关内容

1996年世界足球的风云人物是谁 一探当年最耀眼的球星风采
和365差不多的平台有哪些

1996年世界足球的风云人物是谁 一探当年最耀眼的球星风采

📅 07-21 👁️ 2517
word里面哪个英文字体比较好看
365bet365用址

word里面哪个英文字体比较好看

📅 07-14 👁️ 3902
历史上的喵星人︱古埃及、犹太教和中世纪手稿中的猫