目录:
1.重要类概述
2.重要类的常用方法
2.简单View绘制(圆、圆弧、矩形、弧形、圆角矩形、椭圆、文字等)
3.setXfermode(Xfermode xfermode)的运用
1.重要类概述
在2D绘制中我们常用的类,也是两个最重要的类就是Canvas(画布)和Paint(画笔),通过Canvas我们可以设置
绘制的形状和路径,当然仅仅形状和路径是不行的,我们还需要颜色啊,阴影啊,透明度等等的设置,这时候就是Paint的
事情了,Paint的作用主要就是设置绘图的风格,下面我们就总结一下这两个类常用的方法。
2.重要类的常用方法
(1)Canvas:
构造类方法:
裁切类方法:
图形绘制类方法:
填充类方法:
其他操作类方法:
(2)Paint:
文本设置相关方法:
绘图设置相关方法:
其他方法:
2.简单View绘制(圆、圆弧、矩形、弧形、圆角矩形、椭圆、文字等)
我们通过自定义View的形式来展示我们绘画的图形,所以在此之前我们需要搭建一个自定义View的模型
1.添加自定义类继承View类(待会我们将在onDraw()方法中绘制我们的图形)
2.布局xml文件中应用(通过 包名.类名 的形式 (就像下面com.example.drawview.DrawTextView一样)指定我们定义的类)
接下来我们就可以在onDraw()方法中绘制我们的图形了
(1)圆的绘制
1.1 代码
1.2 效果图
![]()
(2)矩形绘制
2.1 代码
2.2 效果图
![]()
(3)圆角矩形的绘制
3.1 代码
3.2 效果图
![]()
(4)椭圆的绘制
4.1 代码
4.2 效果图
![]()
(5)点的绘制
5.1 代码
5.2 效果图
![]()
(6)线段的绘制
6.1 代码
6.2 效果图
![]()
(7)路径的绘制
7.1 代码
7.2 效果图
![]()
(8)路径文字+简单文字的绘制
8.1 代码
8.2 效果图
![]()
(9)点文字的绘制
9.1 代码
9.2 效果图
![]()
以此实现多样的自定义View。
由于它的混合模式多达18种,下面我只是选取了其中几种,然后分别对不在Canvas上创建新Layer且不限制使用软件渲染与在Canvas上建立新
Layer并且个别模式采用软件渲染模式进行对比,看看他们的区别。如果又需要了解的原理的可以看看下面这篇博客:
http://blog.csdn.net/iispring/article/details/50472485
1)不在Canvas上创建新Layer且不限制使用软件渲染
(1)代码
(2)效果截图
(1)代码
(2)效果截图
![]()
3)PorterDuff.Mode的模式分类
上面这段代码来之源码,看了半天也没看出啥来,话说那些注释是啥意思呢,啥Sa又Da,宝宝头都大了?
网上看了一些文字解释,原来这样:
Sa->Source alpha->源图的Alpha通道
Da->Destination alpha->目标图的Alpha通道
Sc->Source color->源图的颜色
Dc->Destination color ->目标图的颜色
然后呢这样混合过后就组成了最后的ARGB值,形成最终的效果
1.重要类概述
2.重要类的常用方法
2.简单View绘制(圆、圆弧、矩形、弧形、圆角矩形、椭圆、文字等)
3.setXfermode(Xfermode xfermode)的运用
1.重要类概述
在2D绘制中我们常用的类,也是两个最重要的类就是Canvas(画布)和Paint(画笔),通过Canvas我们可以设置
绘制的形状和路径,当然仅仅形状和路径是不行的,我们还需要颜色啊,阴影啊,透明度等等的设置,这时候就是Paint的
事情了,Paint的作用主要就是设置绘图的风格,下面我们就总结一下这两个类常用的方法。
2.重要类的常用方法
(1)Canvas:
构造类方法:
Canvas() //构造方法 Canvas(Bitmap bitmap) //带参构造方法,创建一个以bitmap位图为背景的Canvas
裁切类方法:
clipPath(Path path, Region.Op op) //根据特殊path组合裁切图像,Region.Op定义了Region支持的区域间运算种类。 clipRect(Rect rect, Region.Op op) //根据矩形组合裁切图像 clipRegion(Region region, Region.Op op) concat(Matrix matrix) //通过matrix的设置可以对绘制的图形进行绘制伸缩和位移
图形绘制类方法:
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) //绘制弧形 drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) //绘制bitmap位图 drawPicture(Picture picture, RectF dst) //绘制图片 drawCircle(float cx, float cy, float radius, Paint paint) //绘制圆 drawLine(float startX, float startY, float stopX, float stopY, Paint paint) //绘制线 drawLines(float[] pts, int offset, int count, Paint paint) //可以选择性的去掉一些数据绘制多条线 drawOval(RectF oval, Paint paint) //绘制椭圆 drawPath(Path path, Paint paint) //绘制路径 drawPoint(float x, float y, Paint paint) //绘制点 drawPoints(float[] pts, int offset, int count, Paint paint) //绘制多个点 drawPosText(String text, float[] pos, Paint paint) //绘制文本,float[] pos指定每个文本位置 drawRect(float left, float top, float right, float bottom, Paint paint) //绘制矩形 drawRoundRect(RectF rect, float rx, float ry, Paint paint) //绘制圆角矩形 drawText(String text, float x, float y, Paint paint) //绘制string文本 drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint) //路径上绘制文本
填充类方法:
drawRGB(int r, int g, int b) //使用RGB指定颜色填充canvas的bitmap画布 drawARGB(int a, int r, int g, int b) //使用ARGB指定颜色填充canvas的bitmap画布
其他操作类方法:
save() //保存Canvas状态,save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作 restore() //恢复Canvas之前保存的状态,防止save后对Canvas执行的操作对后续的绘制有影响 rotate(float degrees, float px, float py) //旋转 scale(float sx, float sy) //缩放 skew(float sx, float sy) //扭曲 translate(float dx, float dy) //平移
(2)Paint:
文本设置相关方法:
isUnderlineText() //判断是否有下划线 setUnderlineText(boolean underlineText) //设置下划线 getLetterSpacing() //获取字符间的间距 setLetterSpacing(float letterSpacing) //设置字符间距 getFontSpacing() //获取行间距 isStrikeThruText() //判断文本是否有删除线 setStrikeThruText(boolean strikeThruText) //设置文本删除线 getTextSize() //获取字体大小 setTextSize(float textSize) //设置字体大小 getTypeface() //获取文字字体类型 setTypeface(Typeface typeface) //设置文字字体类型 getTextSkewX() //获取斜体文字的值 setTextSkewX(float skewX) //设置斜体文字的值,负数为右倾斜,正数为左倾斜 官方推荐-0.25 getTextScaleX() //获取文字水平缩放值 setTextScaleX(float scaleX) //设置文本水平缩放值 getTextAlign() //获取文本对其方式 setTextAlign(Paint.Align align) //设置文本对其方式 ascent() //baseline之上至字符最高处的距离 descent() //baseline下面到字符最低处的距离 measureText(CharSequence text, int start, int end) //测绘文本的宽度 getTextBounds(char[] text, int index, int count, Rect bounds) //获取文本宽高 getTextWidths(String text, int start, int end, float[] widths) //精确获取文本宽度 getTextLocale() //获取文本语言地理位置 setTextLocale(Locale locale) //设置文本地理位置,也就是设置对应的语言
绘图设置相关方法:
//设置画笔颜色 setARGB(int a, int r, int g, int b) setAlpha(int a) setColor(int color) //获取画笔颜色 getAlpha() getColor() isAntiAlias() //判断是否抗锯齿 setAntiAlias(boolean aa) //设置抗锯齿,虽然耗资源耗时间,但是一般会开启 getStyle() //获取画笔样式 setStyle(Paint.Style style) //设置画笔样式,FILL:实心; FILL_OR_STROKE:同时实心和空心; STROKE:空心 setStrokeCap(Cap cap) //设置画笔样式, 圆形(Cap.Round),方形(Cap.SQUARE) getStrokeWidth() //获取画笔的粗细大小 setStrokeWidth(float width) //设置画笔的粗细大小 clearShadowLayer() //清除阴影层 setShadowLayer(float radius, float dx, float dy, int shadowColor) //设置阴影 getXfermode() //获取图形绘制的像素融合模式 setXfermode(Xfermode xfermode) //设置图形绘制的像素融合模式和叠加模式,就是新绘制的像素与Canvas上对应位置已有的像素按照混合规则进行颜色混合 getShader() //获取图形的渲染方式 setShader(Shader shader) //设置图形的渲染方式,分别有线性渲染(LinearGradient) 环形渲染(RadialGradient) 组合渲染(ComposeShader) 扫描渐变渲染/梯度渲染(SweepGradient)
其他方法:
reset() //清除画笔复位
2.简单View绘制(圆、圆弧、矩形、弧形、圆角矩形、椭圆、文字等)
我们通过自定义View的形式来展示我们绘画的图形,所以在此之前我们需要搭建一个自定义View的模型
1.添加自定义类继承View类(待会我们将在onDraw()方法中绘制我们的图形)
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-11. */ public class DrawCircleView extends View { Paint paint; public DrawCircleView(Context context) { super(context); } public DrawCircleView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } }
2.布局xml文件中应用(通过 包名.类名 的形式 (就像下面com.example.drawview.DrawTextView一样)指定我们定义的类)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.drawview.MainActivity"> <com.example.drawview.DrawTextView android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout>
接下来我们就可以在onDraw()方法中绘制我们的图形了
(1)圆的绘制
1.1 代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-11. */ public class DrawCircleView extends View { Paint paint; public DrawCircleView(Context context) { super(context); } public DrawCircleView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //初始化画笔 paint = new Paint(); //设置抗锯齿 paint.setAntiAlias(true); //设置画笔颜色 paint.setColor(getResources().getColor(R.color.colorAccent)); //设置画笔要是,圆形/方形/其他 paint.setStrokeCap(Paint.Cap.BUTT); //设置实心圆 paint.setStyle(Paint.Style.FILL); //设置画笔大小 paint.setStrokeWidth(2); //设置阴影 paint.setShadowLayer(5,5,5, Color.BLUE); //绘制实心圆 canvas.drawCircle(300,200,100,paint); //设置为空心 paint.setStyle(Paint.Style.STROKE); //设置画笔大小 paint.setStrokeWidth(3); //绘制 canvas.drawCircle(500,200,100,paint); } }
1.2 效果图
(2)矩形绘制
2.1 代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-15. */ public class DrawRectView extends View { public DrawRectView(Context context) { super(context); } public DrawRectView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); Paint paint = new Paint(); //设置抗锯齿 paint.setAntiAlias(true); //设置画笔的样式 paint.setStrokeCap(Paint.Cap.ROUND); //设置画笔粗细大小 paint.setStrokeWidth(3); //设置画笔的所画图形的样式 paint.setStyle(Paint.Style.FILL); //设置画笔的颜色 paint.setColor(Color.GREEN); //绘制矩形 drawRect(left顶点X坐标, left顶点Y坐标, 右底部X坐标, 右底Y坐标, @NonNull Paint paint) canvas.drawRect(200,200,400,400,paint); //从新设置画笔所画图形样式 paint.setStyle(Paint.Style.STROKE); //重新设置画笔大小 paint.setStrokeWidth(5); //绘制 RectF rect = new RectF(200,420,400,620); canvas.drawRect(rect,paint); } }
2.2 效果图
(3)圆角矩形的绘制
3.1 代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-14. */ public class DrawRoundRectView extends View { public DrawRoundRectView(Context context) { super(context); } public DrawRoundRectView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); //声明并初始化 Paint paint = new Paint(); //设置抗锯齿 paint.setAntiAlias(true); //设置画出的图形是实心还是空心 paint.setStyle(Paint.Style.FILL); //设置画笔粗细 paint.setStrokeWidth(2); //设置画笔的样式 paint.setStrokeCap(Paint.Cap.ROUND); //设置画笔颜色 paint.setColor(getResources().getColor(R.color.colorPrimaryDark)); /* if (Build.VERSION.SDK_INT>=21){ //需要在API 21版本及其以后才能使用,和下面效果相同 canvas.drawRoundRect(100,100,200,200,20,20,paint); }*/ RectF rect = new RectF(200,200,400,400); canvas.drawRoundRect(rect,50,50,paint); //从新设置画笔大小 paint.setStrokeWidth(5); //设置画笔画出的图形未空心 paint.setStyle(Paint.Style.STROKE); //绘制矩形 // RectF(left顶点x坐标, left顶点Y坐标, right边底部x坐标, right边底部Y坐标) RectF rect2 = new RectF(200,420,400,620); //绘制圆角矩形 //drawRoundRect(@NonNull RectF rect, x方向上的圆角半径, Y方向上的圆角半径, @NonNull Paint paint) canvas.drawRoundRect(rect2,50,50,paint); } }
3.2 效果图
(4)椭圆的绘制
4.1 代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.os.Build; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-16. */ public class DrawOvalView extends View { public DrawOvalView(Context context) { super(context); } public DrawOvalView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); Paint paint = new Paint(); //设置抗锯齿 paint.setAntiAlias(true); //设置画笔笔尖样式 paint.setStrokeCap(Paint.Cap.ROUND); //设置所画图形的填充样式 paint.setStyle(Paint.Style.FILL); //设置画笔颜色 paint.setColor(getResources().getColor(R.color.colorAccent)); //实例化一个包裹椭圆的矩形,如果为正方形,则椭圆为圆 RectF rectF = new RectF(200,200,500,400); //设置画布颜色,方便与paint.setColor()对比,看看他们的区别 canvas.drawColor(Color.BLACK); //绘制椭圆 canvas.drawOval(rectF,paint); //设置画笔的大小 paint.setStrokeWidth(5); //设置绘画图形为空心 paint.setStyle(Paint.Style.STROKE); //绘制 if (Build.VERSION.SDK_INT>=21){ //API 21以上才能用,与上面的绘画方式效果一致 canvas.drawOval(200,450,500,650,paint); } } }
4.2 效果图
(5)点的绘制
5.1 代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-16. */ public class DrawPointView extends View { public DrawPointView(Context context) { super(context); } public DrawPointView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); Paint paint = new Paint(); paint.setAntiAlias(true); //设置画笔大小,我这边设置的大点,方便观察 paint.setStrokeWidth(50); //设置画笔笔尖样式,默认为Paint.Cap.SQUARE,待会切换一下,你就会知道它的作用了 // 网上有说在设置paint.setStrokeCap(Paint.Cap.ROUND|SQUARE);之前需要同时设置 //paint.setStrokeJoin(Paint.Join.ROUND|MITER);我测试了好像不需要也能达到切换的目的 paint.setStrokeCap(Paint.Cap.ROUND); paint.setColor(getResources().getColor(R.color.colorAccent)); canvas.drawPoint(200,200,paint); paint.setStrokeCap(Paint.Cap.BUTT); paint.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawPoint(300,200,paint); paint.setStrokeCap(Paint.Cap.SQUARE); paint.setColor(getResources().getColor(R.color.colorAccent)); canvas.drawPoint(400,200,paint); paint.setStrokeCap(Paint.Cap.BUTT); paint.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawPoint(500,200,paint); //设置画笔样式 paint.setStrokeCap(Paint.Cap.ROUND); //设置画笔颜色 paint.setColor(getResources().getColor(R.color.colorAccent)); //绘制多个点 canvas.drawPoints(new float[]{150,300,250,300,350,300,450,300,550,300},paint); } }
5.2 效果图
(6)线段的绘制
6.1 代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Shader; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-16. */ public class DrawLineView extends View { public DrawLineView(Context context) { super(context); } public DrawLineView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); Paint paint = new Paint(); //设置抗锯齿 paint.setAntiAlias(true); //设置画笔样式 paint.setStrokeCap(Paint.Cap.ROUND); //设置画笔颜色 paint.setColor(Color.RED); //设置画笔大小 paint.setStrokeWidth(20); //画线段,参数分别是线段起始点的坐标和终点的坐标,和预设的画笔 canvas.drawLine(100,200,600,200,paint); //LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[], //TileMode tile),(x0,y0) (x1,y1)源码上说是梯度的坐标,不是很懂,我个人理解为后面设置的每一种颜色渲染的长度,坐标间隔越小,渲染的颜色长度越短 //int colors[]:指示需要渲染的颜色数组 float positions[]:可为null,为null时颜色均匀分布 //TileMode tile:指示平铺模式,分别有REPEAT(重复) CLAMP(像素扩散) MIRROR(镜面投影) Shader mShader=new LinearGradient(0,0,100,100, new int[]{Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW}, null,Shader.TileMode.REPEAT); //设置画笔渲染渐变 paint.setShader(mShader); //绘制渐变线段 canvas.drawLine(100,300,600,300,paint); } }
6.2 效果图
(7)路径的绘制
7.1 代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-16. */ public class DrawPathView extends View { public DrawPathView(Context context) { super(context); } public DrawPathView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); //设置抗锯齿 paint.setAntiAlias(true); //设置画笔笔尖样式 paint.setStrokeCap(Paint.Cap.ROUND); //设置填充模式,默认为FILL paint.setStyle(Paint.Style.FILL); //设置画笔大小 paint.setStrokeWidth(3); //设置颜色 paint.setColor(getResources().getColor(R.color.colorPrimary)); /*Path类的几个...To()方法: * path.moveTo(x,y)移动到某个点 * path.lineTo(x,y)从起始点,默认(0,0)点绘制直线到(x,y)点 * path.arcTo()用来绘制弧形 * path.cubicTo()用来绘制贝塞尔曲线 * path.quadTo()也是绘制贝塞尔曲线的 * */ //实例化路径类 Path path = new Path(); //设置移动,不绘制 path.moveTo(200, 200); //从(200,200)画到(200,400) path.lineTo(200, 400); //从(200,400)画到(400,400) path.lineTo(400, 400); //封闭曲线 path.close(); //绘制路径 canvas.drawPath(path, paint); //设置颜色 paint.setColor(getResources().getColor(R.color.colorAccent)); //设置移动,不绘制 Path path1 = new Path(); path1.moveTo(200, 200); //从(200,200)画到(200,400) path1.lineTo(400, 200); //从(200,400)画到(400,400) path1.lineTo(400, 400); //封闭曲线 path1.close(); //绘制 canvas.drawPath(path1, paint); //初始化路径 Path path2 = new Path(); //设置矩形 RectF rectF = new RectF(420, 200, 620, 500); //取矩形包裹椭圆0°到270°的弧 path2.arcTo(rectF, 0, 270); //封闭弧形 path2.close(); //设置填充实心 paint.setStyle(Paint.Style.FILL); //设置画笔颜色 paint.setColor(getResources().getColor(R.color.colorAccent)); //绘制图形 canvas.drawPath(path2, paint); /* *quadTo()绘制贝塞尔曲线 */ Path path3 = new Path(); //移动到(200,620)点 path3.moveTo(200, 620); //绘制贝塞尔曲线 path3.quadTo(300, 420, 400, 620); //设置空心 paint.setStyle(Paint.Style.STROKE); //绘制曲线 canvas.drawPath(path3, paint); /* * cubicTo()绘制贝塞尔曲线 * */ Path path4 = new Path(); //移动到(300,100)点 path4.moveTo(300, 100); //绘制曲线 path4.cubicTo(300, 100, 5, 300, 300, 500); //设置不填充 paint.setStyle(Paint.Style.STROKE); //绘制 canvas.drawPath(path4, paint); } }
7.2 效果图
(8)路径文字+简单文字的绘制
8.1 代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Typeface; import android.os.Build; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-16. */ public class DrawTextView extends View { public DrawTextView(Context context) { super(context); } public DrawTextView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); Paint paint = new Paint(); //设置抗锯齿 paint.setAntiAlias(true); //设置画笔颜色 paint.setColor(getResources().getColor(R.color.colorPrimary)); //设置画笔大小 paint.setStrokeWidth(3); //设置字体大小 paint.setTextSize(30); //设置文字样式 paint.setTypeface(Typeface.DEFAULT_BOLD); String str = "我知道,你要说我很帅,哈啊哈哈哈哈,字不够长!"; //全部显示,起点在(200,100)点 canvas.drawText(str,50,100,paint); //截取4~9的字符串显示 canvas.drawText(str,4,10,200,200,paint); //实例化路径 Path path = new Path(); //设置圆形状路径,Direction指示文字显示是逆时针向外还是顺时针向内 Path.Direction.CW|Path.Direction.CCW path.addCircle(400,400,110, Path.Direction.CW); //更具路径绘制文本 canvas.drawTextOnPath(str,path,0,0,paint); Path path1 = new Path(); if (Build.VERSION.SDK_INT>=21){ //API 21以上 path1.addOval(300,600,500,900, Path.Direction.CCW); } canvas.drawTextOnPath(str,path1,0,0,paint); } }
8.2 效果图
(9)点文字的绘制
9.1 代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-16. */ public class DrawPosTextView extends View { public DrawPosTextView(Context context) { super(context); } public DrawPosTextView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); Paint paint = new Paint(); //设置抗锯齿 paint.setAntiAlias(true); //设置画笔颜色 paint.setColor(getResources().getColor(R.color.colorAccent)); //设置画笔到校 paint.setStrokeWidth(5); //设置字体颜色 paint.setTextSize(30); canvas.drawColor(Color.BLACK); canvas.drawPosText("你看我帅嘛?",new float[]{100,200,200,100,300,200,300,400,200,500,100,400},paint); } }
9.2 效果图
3.setXfermode(Xfermode xfermode)的运用
setXfermode()方法主要是设置图形绘制的像素融合模式和叠加模式,就是新绘制的像素与Canvas上对应位置已有的像素按照混合规则进行颜色混合以此实现多样的自定义View。
由于它的混合模式多达18种,下面我只是选取了其中几种,然后分别对不在Canvas上创建新Layer且不限制使用软件渲染与在Canvas上建立新
Layer并且个别模式采用软件渲染模式进行对比,看看他们的区别。如果又需要了解的原理的可以看看下面这篇博客:
http://blog.csdn.net/iispring/article/details/50472485
1)不在Canvas上创建新Layer且不限制使用软件渲染
(1)代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.os.Build; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-17. */ public class XfermodeView extends View { public XfermodeView(Context context) { super(context); } public XfermodeView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /* * 默认的Xfermode * */ Paint paint = getPaint(); //设置绘制圆的画笔颜色 paint.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(200, 200, 100, paint); //设置绘制圆角矩形的画笔颜色 paint.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上,当然最好是些兼容性好的,我这里只是为了方便 canvas.drawRoundRect(200, 200, 300, 350, 10, 10, paint); /* * PorterDuff.Mode.ADD模式 * */ Paint paint1 = getPaint(); paint1.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(500, 200, 100, paint1); //设置像素融合模式 paint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD)); paint1.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上 canvas.drawRoundRect(500, 200, 600, 350, 10, 10, paint1); //取消像素融合模式的设置 paint1.setXfermode(null); /* * PorterDuff.Mode.CLEAR模式 * */ Paint paint2 = getPaint(); paint2.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(200, 500, 100, paint2); paint2.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); paint2.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上 canvas.drawRoundRect(200, 500, 300, 650, 10, 10, paint2); paint2.setXfermode(null); /* * PorterDuff.Mode.DARKEN模式 * */ Paint paint3 = getPaint(); paint3.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(500, 500, 100, paint3); paint3.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); paint3.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上 canvas.drawRoundRect(500, 500, 600, 650, 10, 10, paint3); paint3.setXfermode(null); /* * PorterDuff.Mode.LIGHTEN模式 * */ Paint paint4 = getPaint(); paint4.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(200, 800, 100, paint4); paint4.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN)); paint4.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上 canvas.drawRoundRect(200, 800, 300, 950, 10, 10, paint4); /* * PorterDuff.Mode.MULTIPLY模式 * */ Paint paint5 = getPaint(); paint5.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(500, 800, 100, paint5); paint5.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); paint5.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上 canvas.drawRoundRect(500, 800, 600, 950, 10, 10, paint5); paint5.setXfermode(null); } public Paint getPaint() { Paint paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(5); return paint; } }
(2)效果截图
(1)代码
package com.example.drawview; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.os.Build; import android.util.AttributeSet; import android.view.View; /** * Created by elimy on 2016-10-17. */ public class XfermodeView extends View { public XfermodeView(Context context) { super(context); } public XfermodeView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /* * 默认的Xfermode * */ Paint paint = getPaint(); //设置绘制圆的画笔颜色 paint.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(200, 200, 100, paint); //设置绘制圆角矩形的画笔颜色 paint.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上,当然最好是些兼容性好的,我这里只是为了方便 canvas.drawRoundRect(200, 200, 300, 350, 10, 10, paint); /* * PorterDuff.Mode.ADD模式 * */ //canvas.saveLayer()在canvas原画布上见一个透明的layer int layerId = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG); Paint paint1 = getPaint(); paint1.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(500, 200, 100, paint1); //设置像素融合模式 paint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD)); paint1.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上 canvas.drawRoundRect(500, 200, 600, 350, 10, 10, paint1); //取消像素融合模式的设置 paint1.setXfermode(null); //将新图层画到canvas上 canvas.restoreToCount(layerId); /* * PorterDuff.Mode.CLEAR模式 * */ int layerId2 = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG); Paint paint2 = getPaint(); paint2.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(200, 500, 100, paint2); paint2.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); paint2.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上 canvas.drawRoundRect(200, 500, 300, 650, 10, 10, paint2); paint2.setXfermode(null); canvas.restoreToCount(layerId2); /* * PorterDuff.Mode.DARKEN模式 * */ int layerId3 = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG); Paint paint3 = getPaint(); paint3.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(500, 500, 100, paint3); //禁用掉CPU硬件加速,采用软件渲染模式,因为DARKEN、LIGHTEN、OVERLAY等几种混合规则在GPU硬件加速效果展示不出来 this.setLayerType(View.LAYER_TYPE_SOFTWARE, null); paint3.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); paint3.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上 canvas.drawRoundRect(500, 500, 600, 650, 10, 10, paint3); paint3.setXfermode(null); canvas.restoreToCount(layerId3); /* * PorterDuff.Mode.LIGHTEN模式 * */ int layerId4 = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG); Paint paint4 = getPaint(); paint4.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(200, 800, 100, paint4); this.setLayerType(View.LAYER_TYPE_SOFTWARE, null); paint4.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.LIGHTEN)); paint4.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上 canvas.drawRoundRect(200, 800, 300, 950, 10, 10, paint4); paint4.setXfermode(null); canvas.restoreToCount(layerId4); /* * PorterDuff.Mode.MULTIPLY模式 * */ int layerId5 = canvas.saveLayer(0, 0, canvas.getWidth(), canvas.getHeight(), null, Canvas.ALL_SAVE_FLAG); Paint paint5 = getPaint(); paint5.setColor(getResources().getColor(R.color.colorPrimary)); canvas.drawCircle(500, 800, 100, paint5); paint5.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); paint5.setColor(getResources().getColor(R.color.colorAccent)); if (Build.VERSION.SDK_INT >= 21) //API 21以上 canvas.drawRoundRect(500, 800, 600, 950, 10, 10, paint5); paint5.setXfermode(null); canvas.restoreToCount(layerId5); } public Paint getPaint() { Paint paint = new Paint(); paint.setAntiAlias(true); paint.setStyle(Paint.Style.FILL); paint.setStrokeWidth(5); return paint; } }
(2)效果截图
3)PorterDuff.Mode的模式分类
/** [0, 0] */ CLEAR (0), /** [Sa, Sc] */ SRC (1), /** [Da, Dc] */ DST (2), /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */ SRC_OVER (3), /** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */ DST_OVER (4), /** [Sa * Da, Sc * Da] */ SRC_IN (5), /** [Sa * Da, Sa * Dc] */ DST_IN (6), /** [Sa * (1 - Da), Sc * (1 - Da)] */ SRC_OUT (7), /** [Da * (1 - Sa), Dc * (1 - Sa)] */ DST_OUT (8), /** [Da, Sc * Da + (1 - Sa) * Dc] */ SRC_ATOP (9), /** [Sa, Sa * Dc + Sc * (1 - Da)] */ DST_ATOP (10), /** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */ XOR (11), /** [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */ DARKEN (12), /** [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */ LIGHTEN (13), /** [Sa * Da, Sc * Dc] */ MULTIPLY (14), /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */ SCREEN (15), /** Saturate(S + D) */ ADD (16), OVERLAY (17);
上面这段代码来之源码,看了半天也没看出啥来,话说那些注释是啥意思呢,啥Sa又Da,宝宝头都大了?
网上看了一些文字解释,原来这样:
Sa->Source alpha->源图的Alpha通道
Da->Destination alpha->目标图的Alpha通道
Sc->Source color->源图的颜色
Dc->Destination color ->目标图的颜色
然后呢这样混合过后就组成了最后的ARGB值,形成最终的效果
作者:qq_28057577 发表于2016/10/18 11:50:01 原文链接
阅读:42 评论:0 查看评论