Canvas(画布):通过Canvas设置绘制的形状和路径
Paint(画笔):通过Paint设置颜色、阴影、透明度等等
Android API Paint 使用方法总结:https://blog.csdn.net/shell812/article/details/49781397?ref=myread
isUnderlineText() //判断是否有下划线
setUnderlineText(boolean underlineText) //设置下划线
setLinearText(boolean linearText) //设置线性文本
getLetterSpacing() //获取字符间的间距
setLetterSpacing(float letterSpacing) //设置字符间距
getFontSpacing() //获取行间距
isStrikeThruText() //判断文本是否有删除线
setStrikeThruText(boolean strikeThruText) //设置文本删除线
getTextSize() //获取字体大小
setTextSize(float textSize) //设置字体大小
setFakeBoldText(boolean fakeBoldText) //设置伪粗体文本,设置在小字体上效果会非常差
getTextSkewX() //获取斜体文字的值
setTextSkewX(float skewX) //设置斜体文字的值,负数为右倾斜,正数为左倾斜 官方推荐-0.25
getTextScaleX() //获取文字水平缩放值
setTextScaleX(float scaleX) //设置文本水平缩放值 1.0为原始值
getTextAlign() //获取文本对其方式
setTextAlign(Paint.Align align) //设置文本对其方式 参数:Paint.Align.center,Paint.Align.left,Paint.Align.right
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) //设置文本地理位置,也就是设置对应的语言
setSubpixelText(boolean subpixelText) 参数:true或者false 设置为true,将有助于文本在LCD屏幕上的显示效果getTypeface() //获取文字字体类型
setTypeface(Typeface typeface) ///设置字体风格,包括粗体,斜体以及衬线体,非衬线体等
常用的字体类型名称: Typeface.DEFAULT //常规字体类型 Typeface.DEFAULT_BOLD //黑体字体类型 Typeface.MONOSPACE //等宽字体类型 Typeface.SANS_SERIF //sans serif字体类型 常用的字体风格名称: Typeface.BOLD //粗体 Typeface.BOLD_ITALIC //粗斜体 Typeface.ITALIC //斜体 Typeface.NORMAL //常规
控件的字体设置的两种方式
1.在xml中设置。
使用android:typeFace来设置:
Android:typeface=”sans”
2.在Java程序中:
eg1:Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD); p.setTypeface( font );
eg2:
String familyName = “宋体”; Typeface font = Typeface.create(familyName,Typeface.BOLD); p.setTypeface(font);
//设置画笔颜色
setARGB(int a, int r, int g, int b) //设置透明度和颜色 a:透明度,取值范围为0~255,数值越小越透明。 r:红色的颜色值,取值范围为0~255。 g:绿色的颜色值,取值范围为0~255。setAlpha(int a) //设置透明度0~255,要在setColor后面设置才生效 常用于一些图片重叠或者特效显示的场合 b:蓝色的颜色值,取值范围为0~255。
setColor(int color)
eg:setColor(getResources().getColor(R.color.colorAccent))
R.color:
colorPrimary – 应用程序工具条的颜色。 colorPrimaryDark – 状态条的颜色,它是深色的colorPrimary 。 colorAccent – 控件颜色,例如复选框、单选按钮、文本框等。 windowBackground – 屏幕背景色。 textColorPrimary – 应用程序的文本颜色。 statusBarColor – 状态条颜色。 navigationBarColor – 导航条颜色。
//获取画笔颜色
getAlpha()
getColor()
isAntiAlias() //判断是否抗锯齿
setAntiAlias(boolean aa) //设置抗锯齿,虽然耗资源耗时间,但是一般会开启 (边缘柔化处理) setDither(boolean dither) //设定是否使用图像抖动处理,会使绘制出来的图片颜色更加平滑和饱满,图像更加清晰
setFilterBitmap(boolean filter) //如果该项设置为true,则图像在动画进行中会滤掉对Bitmap图像的优化操作来加快显示速度,本设置项依赖于dither和xfermode的设置
getStyle() //获取画笔样式
setStyle(Paint.Style style) //设置画笔样式 实心:Paint.Style.FILL 空心:Paint.Style.STROKE 同时实心和空心 : Paint.Style.FILL_OR_STROKE
setStrokeWidth(float width) //当画笔样式为STROKE或FILL_OR_STROKE时,设置笔刷的粗细度
setStrokeMiter(float miter)
getStrokeWidth() //获取画笔的粗细大小 setStrokeCap(Cap cap) //当画笔样式为STROKE或FILL_OR_STROKE时,设置线帽样式(笔刷末端的图形样式) 参数:Paint.Cap.ROUND(圆形线冒)、Paint.Cap.SQUARE(方形线冒)、 Paint.Cap.BUTT(无线冒)
setStrokeJoin(Join join) //设置绘制时各图形结合处的形态,如线段的连接处的样式是圆滑还是尖锐 参数:Paint.Join.MITER //锐角连接 Paint.Join.ROUND //圆弧连接 Paint.Join.BEVEL //斜接(用斜边替换)
clearShadowLayer() //清除阴影层
setShadowLayer(float radius, float dx, float dy, int shadowColor) //设置阴影 //在图形下面设置阴影层,产生阴影效果 参数:radius:阴影角度 dx和dy:阴影在x轴和y轴上的距离 color:阴影的颜色
//注意:在Android4.0以上默认开启硬件加速,有些图形的阴影无法显示。 //关闭View的硬件加速 view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
getXfermode() //获取图形绘制的像素融合模式
setXfermode(Xfermode xfermode) //设置图形绘制的像素融合模式和叠加模式,就是新绘制的像素与Canvas上对应位置已有的像素按照混合规则进行颜色混合
getShader() //获取图形的渲染方式
setShader(Shader shader) //设置图形的渲染方式,线性渲染(LinearGradient) 环形渲染(RadialGradient) 组合渲染(ComposeShader) 扫描渐变渲染/梯度渲染(SweepGradient)LinearGradient 线性渲染方式: LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],TileMode tile) //渐变效果 参数:(x0,y0) 梯度的起点坐标,渐变相对父容器的起始点 (x1,y1) 梯度的终点坐标,渐变相对父容器的终点 int colors[]:需要渲染的颜色数组 float positions[]: float类型的数组,表示colors数组中几个颜色的相对位置,数组的长度必须与colors数组的长度相同,可设置为null,为null时颜色均匀分布
TileMode tile:指示平铺模式,TileMode.REPEAT(重复) TileMode.CLAMP(像素扩散) TileMode.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);
setColorFilter(ColorFilter filter) //设置滤镜效果,通过色彩矩阵实现颜色过滤 具体设置方法参考:https://blog.csdn.net/aigestudio/article/details/41316141
setXfermode(Xfermode xfermode) //设置图形重叠时的处理方式(图像混合模式),如合并,取交集或并集,经常用来制 作橡皮的擦除效果 具体的参考:https://blog.csdn.net/speverriver/article/details/70243329 https://www.cnblogs.com/libertycode/p/6290497.html
setMaskFilter(MaskFilter maskfilter) //两个子类 BlurMaskFilter:模糊遮罩滤镜 EmbossMaskFilter:浮雕遮罩滤镜 具体的参考:https://www.cnblogs.com/tianzhijiexian/p/4297734.htmlsetPathEffect(PathEffect effect) //设置绘制路径的效果,将PathEffect类应用到Paint对象中。 详情参考: Android图形之PathEffect类 https://www.cnblogs.com/zswcloud/p/3966568.html
setRasterizer(Rasterizer rasterizer) //设置光栅化,涉及太多物理知识,不推荐使用
reset() //清除画笔复位
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) //clipRect和clipPath要使用当前的矩阵进行变换。而clipRegion不会进行 转换。也就是说canvas的矩阵对clipRegion没有影响。
concat(Matrix matrix) //通过matrix的设置可以对绘制的图形进行绘制伸缩和位移
drawRGB(int r, int g, int b) //使用RGB指定颜色填充canvas的bitmap画布
drawARGB(int a, int r, int g, int b) //使用ARGB指定颜色填充canvas的bitmap画布
绘制点:
drawPoint(float x, float y, Paint paint) //绘制一个点
drawPoints(float[] pts, int offset, int count, Paint paint) //绘制多个点
绘制线条:
drawLine(float startX, float startY, floatstop X, floatstopY, Paint paint)
drawLines(float[] pts, int offset, int count, Paint paint) //可以选择性的去掉一些数据绘制多条线
绘制矩形:
drawRect(RectF rect, Paint paint) drawRect(float left, float top, float right, float bottom, Paint paint) 参数:(left,top):左顶点坐标 (right,bottom):右底点坐标
canvas.drawRect(50, 400, 450, 600, paint); //绘制矩形 (1) Rect r=new Rect(); //Rect对象 (2) r.left=50; //左边 r.top=50; //上边 r.right=450; //右边 r.bottom=250; //下边 canvas.drawRect(r, paint); //绘制矩形
绘制圆角矩形:
drawRoundRect(RectF rect, float rx, float ry, Paint paint) drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint) 参数:(left,top):左顶点坐标 (right,bottom):右底点坐标 rx:x方向的圆角半径 ry:y方向的圆角半径
绘制圆:
drawCircle(float cx, float cy, float radius,Paint paint) 参数:(cx,cy)圆心坐标 radius:圆半径 paint:绘制风格
绘制椭圆:
drawOval(RectF oval, Paint paint) drawOval(float left, float top, float right, float bottom, Paint paint) 参数:left>图形left的x坐标
top>图形top的y坐标
right>图形right的x坐标
bottom>图形bottom的y坐标
paint>绘制风格
绘制圆弧:
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint) //绘制弧形 参数:oval :指定圆弧的外轮廓矩形区域。
startAngle: 圆弧起始角度,单位为度。
sweepAngle: 圆弧扫过的角度,顺时针方向,单位为度。
useCenter: 如果为True时,在绘制圆弧时将圆心包括在内,通常用来绘制扇形。
paint: 绘制圆弧的画板属性,如颜色,是否填充等。
绘制String文字:
drawText(String text, float x, float y,Paint paint) 参数:text 文本
(x,y)文字的起点坐标:左下角
paint>绘制风格DrawText详解:https://blog.csdn.net/qqqq245425070/article/details/79027979
绘制文本:
drawPosText(String text, float[] pos, Paint paint) // float[] pos指定每个文本位置
路径上绘制文本:
drawTextOnPath(char[] text, int index, int count, Path path, float hOffset, float vOffset, Paint paint)
绘制Bitmap图:
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
绘制图片:
drawPicture(Picture picture, RectF dst)
drawPath(Path path, Paint paint)
//添加子图形和画线(直线或曲线)
可添加的子图形:
addCircle(float x, float y, float radius, Direction dir) //添加圆
addOval(float left, float top, float right, float bottom, Direction dir) //添加椭圆
addOval(RectF oval, Direction dir)
addRect(float left, float top, float right, float bottom, Direction dir) //添加矩形
addRect(RectF rect, Direction dir)
addRoundRect(RectF rect, float rx, float ry, Direction dir) //添加圆角矩形
addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Direction dir)
addRoundRect(RectF rect, float[] radii, Direction dir)
addRoundRect(float left, float top, float right, float bottom, float[] radii, Direction dir)
addPath(Path path) //添加另一个 Path
addArc (RectF oval, float startAngle, float sweepAngle)
//RectF oval:矩形区域
//float startAngle:开始的角度,X轴正方向为0度
//float sweepAngel:持续的度数;
参考:drawPath():https://blog.csdn.net/yy471101598/article/details/78543459
(1)画直线:lineTo(float x, float y) //起点坐标:当前画笔所在的点 终点坐标:(x,y)
rLineTo(float x, float y) //起点坐标:当前画笔所在的点 终点坐标:(起点+x,起点+y)
(2)画 二次贝塞尔曲线:quadTo(float x1, float y1, float x2, float y2) //控制点坐标:(x1,y1) 终点坐标:(x2,y2)
rQuadTo(float dx1, float dy1, float dx2, float dy2) //dx1:控制点相对起点的x位移 dy1:控制点相对起点的y位移
终点坐标=(起点x坐标+dx2,起点y坐标+dy2)
贝塞尔曲线详解:https://blog.csdn.net/asdfasfasfs/article/details/78024490
https://blog.csdn.net/tianjian4592/article/details/46955833
画 三次贝塞尔曲线:cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
rCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
(3)移动到目标位置:moveTo(float x, float y)
rMoveTo(float x, float y)
(4)画弧线:arcTo(RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo)
arcTo(RectF oval, float startAngle, float sweepAngle)
//oval:弧线所在矩形区域
//startAngle:弧线的起始角度
//sweepAngle:弧线所划过的角度
//forceMoveTo :默认为false,则画笔画完圆弧之后,画笔落笔点变为圆弧起始位置,造成画笔最初的落笔点和圆弧画完之后的落笔点之间形成一条直线路径,参数若设置为true,则绘制效果与
addArc
方法没有区别代码:
super.onDraw(canvas); Paint paint = new Paint(); //设置抗锯齿 paint.setAntiAlias(true); //设置画笔笔尖样式 paint.setStrokeCap(Paint.Cap.ROUND); //设置所画图形的填充样式 paint.setStyle(Paint.Style.STROKE); //设置画笔颜色 paint.setColor(getResources().getColor(R.color.colorAccent)); Rect rect = new Rect(100, 100, 300, 250);//矩形 canvas.drawRect(rect, paint); Path path = new Path(); path.moveTo(0, 0); path.arcTo(new RectF(rect), 0, 90); //path.addArc(new RectF(rect), 0, 90); canvas.drawPath(path, paint);
arcTo和addArc的区别:
1. addArc可以直接加入一段椭圆弧。使用arcTo需要使用moveTo来指定画笔最初落笔点坐标。
path.moveTo(0, 0);
2. arcTo如果当前点坐标和曲线的起始点不是同一个点的话,还会自动添加一条直线补齐路径。
作用:把当前的轮廓图形封闭,即由当前落笔点位置向当前子图形的起始落笔点位置绘制一条直线。
paint.setStyle(Style.STROKE);
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(150, 150);
// 子图形未封闭
paint.setStyle(Style.STROKE);
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(150, 150);
path.close(); // 使用 close() 封闭子图形。等价于 path.lineTo(100, 100)
close() 和 lineTo(起点坐标) 是完全等价的。
注意:不是所有的子图形都需要使用 close() 来封闭。当需要填充图形时(即 Paint.Style 为 FILL 或 FILL_AND_STROKE),Path 会自动封闭子图形
paint.setStyle(Style.FILL);
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(150, 150);
// 这里只绘制了两条边,但由于 Style 是 FILL ,所以绘制时会自动封口
Path.setFillType(Path.FillType ft) //设置填充方式
Path.setFillType(fillType) 是用来设置图形自相交时的填充算法的.
方法中填入不同的 FillType 值,就会有不同的填充效果。FillType 的取值有四个:
Path.FillType.EVEN_ODD
Path.FillType.WINDING (默认值)
Path.FillType.INVERSE_EVEN_ODD (上面两个的反色版本)
Path.FillType.INVERSE_WINDING
即 even-odd rule (奇偶原则):对于平面中的任意一点,向任意方向射出一条射线,这条射线和图形相交的次数(相交才算,相切不算哦)如果是奇数,则这个点被认为在图形内部,是要被涂色的区域;如果是偶数,则这个点被认为在图形外部,是不被涂色的区域。还以左右相交的双圆为例:
non-zero winding rule (非零环绕数原则):内部被涂色,外部不被涂色 内部外部和画图形时路径为顺时针还是逆时针有关
首先,它需要你图形中的所有线条都是有绘制方向的:
然后,同样是从平面中的点向任意方向射出一条射线,但计算规则不一样:以 0 为初始值,对于射线和图形的所有交点,遇到每个顺时针的交点(图形从射线的左边向右穿过)把结果加 1,遇到每个逆时针的交点(图形从射线的右边向左穿过)把结果减 1,最终把所有的交点都算上,得到的结果如果不是 0,则认为这个点在图形内部,是要被涂色的区域;如果是 0,则认为这个点在图形外部,是不被涂色的区域。
图形的方向:对于添加子图形类方法(如 Path.addCircle() Path.addRect())的方向,由方法的 dir 参数来控制;而对于画线类的方法(如 Path.lineTo() Path.arcTo())就更简单了,线的方向就是图形的方向。
addCircle(float x, float y, float radius, Direction dir) //添加圆
addOval(float left, float top, float right, float bottom, Direction dir) //添加椭圆
addOval(RectF oval, Direction dir)
addRect(float left, float top, float right, float bottom, Direction dir) //添加矩形
addRect(RectF rect, Direction dir)
addRoundRect(RectF rect, float rx, float ry, Direction dir) //添加圆角矩形
addRoundRect(float left, float top, float right, float bottom, float rx, float ry, Direction dir)
addRoundRect(RectF rect, float[] radii, Direction dir)
addRoundRect(float left, float top, float right, float bottom, float[] radii, Direction dir)
Path.Direction.CCW:是counter-clockwise缩写,指创建逆时针方向的矩形路径;
Path.Direction.CW:是clockwise的缩写,指创建顺时针方向的矩形路径;
详情:Canvas之translate、scale、rotate、skew方法讲解:https://blog.csdn.net/tianjian4592/article/details/45234419
save() //保存Canvas状态,save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作
restore() //恢复Canvas之前保存的状态,防止save后对Canvas执行的操作对后续的绘制有影响translate(float dx, float dy) //平移 (x轴方向,y轴方向)
rotate(float degrees)旋转 degrees:旋转角度 值为角度数 0~360
rotate(float degrees, float px, float py) //degrees:旋转角度 (px,py):基准点
scale(float sx, float sy) //缩放 以(0,0)为基准点,沿着x方向y方向缩放 final void scale (float sx,float sy, float px, float py); 以(px,py)为基准点,沿着x方向y方向缩放
skew(float sx, float sy) //扭曲 sx:将画布在x方向上倾斜相应的角度,sx为倾斜角度的tan值; sy:将画布在y轴方向上倾斜相应的角度,sy为倾斜角度的tan值; 注意,这里全是倾斜角度的tan值,比如我们打算在X轴方向上倾斜45度,tan45=1;Canvas之translate、scale、rotate、skew方法讲解:https://blog.csdn.net/tianjian4592/article/details/45234419
Draw的过程:
1、View的初始化
public CarsonView(Context context) {
super(context);
}
public CarsonView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CarsonView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//
//可以在View初始化的时候 初始化画笔,如:设置颜色
//也可以在onDrow的时候初始化画笔
}
public CarsonView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
}
例子:
/**
* 字体颜色
*/
private int mTextColor = 0xff0000ff;
/**
* 画笔
*/
private Paint mPaint;
/**
* 绘制的文本
*/
private String text = "HelloWorld";
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//初始化画笔,设置字体大小,颜色
mPaint = new Paint();
mPaint.setTextSize(sp2px(20));
mPaint.setColor(mTextColor);
setBackgroundColor(Color.parseColor("#fff1f1f1"));
}
public CustomTextView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CustomTextView(Context context) {
this(context,null);
}
2、onMeasure(int widthMeasureSpec, int heightMeasureSpec) :存储测量后的View宽 / 高
设置该View的大小为文字的大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//存储测量后的View宽 / 高
//设置该View的大小为文字的大小
int width = (int) mPaint.measureText(text);
int height = (int) Math.abs(mPaint.descent()-mPaint.ascent());
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
3、onDraw(Canvas canvas):开始绘制
@Override
protected void onDraw(Canvas canvas) {
//在canvas上画出文字,参数分别为:文本字符串,文字X和Y的偏移,画笔
canvas.drawText(text, 0, getHeight()-mPaint.descent(), mPaint);
}