Canvas类提供丰富的绘图方法,想要绘出一个漂亮的控件,这些方法坑定是要熟练使用的。最近花了一点时间来熟悉一下这些常用的方法。在这边一一记下,哪怕一时忘记,也可以过来看看立马回忆起来。
这边我通过继承View,并重写onDraw方法来练习
为了解释方便,参数1,参数2分别用P1和P2来表示后面参数以此类推
绘制网格
为了能更宏观的观察坐标系,給画上网格和坐标
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
int interval = 100;
{
Paint paint = new Paint();
paint.setStrokeWidth(2);
paint.setColor(Color.RED);
for (int i=0; i < height; i=i+interval) {
canvas.drawLine(0, i, width, i,paint);
}
for (int j=0; j < width; j=j+interval) {
canvas.drawLine(j, 0, j, height,paint);
}
paint.setTextSize(25);
paint.setTypeface(Typeface.MONOSPACE);
Paint point = new Paint();
point.setColor(Color.YELLOW);
point.setStrokeWidth(3);
for (int x=0; x < width; x=x+2*interval){
for (int y=0; y < height; y=y+2*interval) {
canvas.drawText("("+x+","+y+")",x,y+25,paint);
canvas.drawPoint(x, y, point);
}
}
}
绘制直线
绘制直线有三个方法
绘制单条直线,给定端点绘制
绘制多条直线,给定一定数量的float,分别4个数表示一个条单个直线,所以数组长度要是4的倍数
是对方法2的一个扩展,有时候给定数组我们并想全部绘出,只想绘出部分直线,这边便可以通过接下来的2个参数来控制,跳过的多少长度,到某个长度以内的直线。
{
Paint paint = new Paint();
paint.setStrokeWidth(2);
paint.setColor(Color.GREEN);
canvas.drawLine(0, 0, 200, 200, paint);
canvas.drawLines(new float[]{200, 200, 400, 0}, paint);
canvas.drawLines(new float[]{400, 0, 600, 200, 600, 200, 800, 0}, 0, 8, paint);
}
绘制圆
这个很好理解,参数P1和P2分别是圆心x和y坐标,P3是半径
圆形包括一下一些对象都是形状,所以在绘出时会有2中样子,实心和空心(或是填充或是描边)
{
Paint paint = new Paint();
paint.setColor(Color.GREEN);
canvas.drawCircle(100, 300, 100, paint);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(300, 300, 100, paint);
}
绘制弧线
RectF表示一个抽象的矩形对象,基本构造就是(left,top,right,bottom)弧线就会在这个矩形框内绘出,且与4个边相切。
P2是起始角度,P3是结束角度
弧线说穿了算是一个残缺的椭圆,所以有圆心,所有Android为我们提供了P4(当true时连到两个端点会连接中心,false时端点会直接相连)
{
Paint paint = new Paint();
paint.setColor(Color.GREEN);
canvas.drawArc(new RectF(400, 200, 600, 400), 90, 130, true, paint);
canvas.drawArc(new RectF(600, 200, 800, 400), 90, 130, false, paint);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(2);
canvas.drawArc(new RectF(800, 200, 1000, 400), 90, 130, true, paint);
canvas.drawArc(new RectF(800, 0, 1000, 200), 90, 130, false, paint);
}
绘制矩形
非常简单只要,只要指定(left,top,right,bottom)
{
Paint paint = new Paint();
paint.setColor(Color.GREEN);
canvas.drawRect(0, 400, 200, 600, paint);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(200, 400, 400, 600, paint);
}
绘制圆角矩形
与矩形绘制类似除了要指定RectF参数外,还需要指定圆角的大小P2(x轴方向圆角半径),P3(y轴方向圆角半径)
{
Paint paint = new Paint();
paint.setColor(Color.GREEN);
canvas.drawRoundRect(new RectF(400, 400, 600, 600), 40, 40, paint);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRoundRect(new RectF(600, 400, 800, 600), 40, 40, paint);
}
绘制椭圆
绘制椭圆与绘制圆弧很像,都需要指定一个矩形区域,系统会自动在该区域绘制椭圆
````java
//椭圆
{
Paint paint = new Paint();
paint.setColor(Color.GREEN);
//实心椭圆
canvas.drawOval(new RectF(0, 600, 400, 800), paint);
//空心椭圆
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawOval(new RectF(400, 600, 800, 800), paint);
}
#### 绘制路径
>强大的路径,几乎拥有它其他皆可以抛弃
这边可以能需要介绍下Path类及一些操作方法
- public void moveTo(float x, float y)
移动到某个绝对坐标,它不会留下任何绘图痕迹,只是移动这一抽象动作
- public void rMoveTo(float dx, float dy)
与上一个方法类似也是用于移动,不过它移动的距离是相对当前坐标(Path类中提供很多 r***( ... ) 都是相对坐标,所以以下不再一一列出)
- public void lineTo(float x, float y)
从当前点到x和y画一条直线
- public void addArc(RectF oval, float startAngle, float sweepAngle)
画一个圆弧
- public void arcTo(RectF oval, float startAngle, float sweepAngle)
画一个圆弧,并且起点与当前点相连
这边就先介绍到这里,还有其他一些强大的功能暂时没时间看
```java
{
Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStrokeWidth(2);
Path path = new Path();
path.moveTo(0, 800);
path.rLineTo(100, 50);
path.rLineTo(100, -50);
path.rLineTo(-50, 100);
path.rLineTo(50, 100);
path.rLineTo(-100, -50);
path.rLineTo(-100, 50);
path.rLineTo(50, -100);
path.close();
canvas.drawPath(path, paint);
paint.setStyle(Paint.Style.STROKE);
path.reset();
path.moveTo(200, 800);
path.rLineTo(100, 50);
path.rLineTo(100, -50);
path.rLineTo(-50, 100);
path.rLineTo(50, 100);
path.rLineTo(-100, -50);
path.rLineTo(-100, 50);
path.rLineTo(50, -100);
path.close();
canvas.drawPath(path, paint);
path.reset();
path.moveTo(400, 800);
path.lineTo(500, 800);
path.arcTo(new RectF(400, 800, 600, 1000), 0, 45, false);
path.arcTo(new RectF(400, 800, 600, 1000), 90, 120, true);
canvas.drawPath(path, paint);
}
绘制渐变效果
这里的渐变大致可以分3种
线性渐变 - 直线渐变
圆形渐变-由内圈到外圈的渐变
角度渐变 - 360度的渐变效果
P1~P4为渐变的直线方向,P5为颜色数组,P6为颜色在渐变种所处位置
{
Paint paint = new Paint();
LinearGradient linearGradient = new LinearGradient(0,0,100,0,new int[]{Color.argb(255,50,50,50),Color.argb(255,200,200,200),Color.argb(255,50,50,50)},new float[]{0,0.5f,1}, Shader.TileMode.MIRROR);
paint.setShader(linearGradient);
paint.setTextSize(30);
canvas.drawText("线性渐变",0,1100,paint);
RadialGradient radialGradient = new RadialGradient(300, 1100, 100, Color.GREEN, Color.TRANSPARENT, Shader.TileMode.MIRROR);
paint.setShader(radialGradient);
paint.setTextSize(30);
canvas.drawCircle(300, 1100,100, paint);
SweepGradient sweepGradient = new SweepGradient(500,1100,Color.GREEN,Color.TRANSPARENT);
paint.setShader(sweepGradient);
canvas.drawArc(new RectF(400, 1000, 600, 1200), 0, 360, true, paint);
}
绘制阴影
设置阴影是通过设置Paint的ShadowLayer参数P1为扩散半径,P2,P3分别为x和y轴偏移位置
有个注意点,就是当没有效果时可能需要通过setLayerType(LAYER_TYPE_SOFTWARE, null);来关闭硬件加速
因为有些绘制效果在硬件加速下无法正常显示。
{
Paint paint = new Paint();
paint.setColor(Color.GREEN);
paint.setTextSize(30);
paint.setShadowLayer(5, 10, 10, Color.RED);
setLayerType(LAYER_TYPE_SOFTWARE, null);
canvas.drawText("有阴影的字", 650, 1100, paint);
}
}
整个以上例子的效果如下图