您的位置:首页 > 其它

自定义View学习笔记04—Canvas的绘制图形

2017-12-25 18:11 691 查看
前面通过深入学习,通过3篇笔记详细的记录了自定义View的一些基础知识,从这篇开始正式进入自定义View的大门。

TODO:Canvas可以绘制的对象有:弧线(arcs)、填充颜色(argb和color)、 Bitmap、圆(circle和oval)、点(point)、线(line)、矩形(Rect)、图片(Picture)、

圆角矩形 (RoundRect)、文本(text)、顶点(Vertices)、路径(path)。

TODO:Canvas位置转换的方法:rorate、scale、translate、skew(扭曲)等

TODO:Canvas 还提供了保存和回滚属性的方法(save和restore),比如你可以先保存目前画纸的位置(save),

然后旋转90度,向下移动100像素后画一些图形,画完后调用restore方法返回到刚才保存的位置

本文先讲Canvas绘制填充颜色(argb和color)、弧线(arcs)、圆(circle和oval)、点(point)、线(line)、(圆角)矩形Rect/RoundRect,下一篇笔记再讲图片(Picture)、文本(text)、顶点(Vertices)、路径(path)、Bitmap。

我们先从自定义View的常见步骤开始:

public class MyCanvas extends View {
public static int widthSize = 0;
public static int heightSize = 0;
public static Paint mPaint = null;
private String textContent;
private float textSize = 0f;
private float minTextSize = 16f;
private Context mContext;

public String getTextContent() {
return textContent;
}

public void setTextContent(String textContent) {
this.textContent = textContent;
}

public MyCanvas(Context context) {
super(context);
mContext = context;
if(mPaint == null){
initPaint();//实例化画笔对象;
}
}

public MyCanvas(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
if(mPaint == null){
initPaint();//实例化画笔对象;
}
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heiSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int widSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heiSpecSize = MeasureSpec.getSize(heightMeasureSpec);
DisplayMetrics metrics = getResources().getDisplayMetrics();
if (widSpecMode == MeasureSpec.AT_MOST &&
heiSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(metrics.widthPixels,
DisplayUtils.dpToPx(mContext, 300));
}else if(widSpecMode == MeasureSpec.AT_MOST){
setMeasuredDimension(metrics.widthPixels, heiSpecSize);
}else if(heiSpecMode == MeasureSpec.AT_MOST){
setMeasuredDimension(widthMeasureSpec,
DisplayUtils.dpToPx(mContext, 300));
}
}

//int w, int h:自定义View的最终大小
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(widthSize, heightSize, oldw, oldh);
widthSize = w;
heightSize = h;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//自定义View的各方法可以根据需要在这里调用,如:
drawColor(canvas);//绘制纯色(界面为某个指定的颜色)
}
}


我们再来看看自定义的View如何在Activity里面使用:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_canvas);
LinearLayout llCanvas = (LinearLayout) findViewById(R.id.llCanvas);
MyCanvas mCanvas = new MyCanvas(CanvasActivity.this);
llCanvas.addView(mCanvas);
}


现在我们正式开始自定义View的基础学习:

1、绘制纯色(为界面指定某个颜色):drawColor(int color)

private void drawColor(Canvas canvas){
canvas.drawColor(Color.parseColor("#99ff00ff"));
//或者:
//canvas.drawColor(Color.BLUE);
}


在MyCanvas的onDraw()方法里调用该方法,效果如下:



2、绘制点(包括一系列的点):drawPoint(float x, float y, Paint paint)、

drawPoints(float[] pts,Paint paint)

private void drawPoint(Canvas canvas){
//一系列的点
float array = new float[]{28,28,56,56,84,84,112,112,140,140}
canvas.drawPoints(array , mPaint);
mPaint.setColor(Color.parseColor("#0000ff"));
mPaint.setStrokeWidth(12);
//单个点
canvas.drawPoint(500, 500, mPaint);
}


在MyCanvas的onDraw()方法里调用该方法,效果如下:



3、绘制直线(包含一系列的):drawLine(float startX, float startY, float stopX, float stopY, Paint paint)、drawLines(float[] pts, Paint paint)

private void drawLine(Canvas canvas){
mPaint.setStrokeWidth(5f);
mPaint.setColor(Color.BLACK);
canvas.drawLine(100,220,480,230, mPaint);
canvas.drawLines(new float[]{300,320,420,430,
420,430,580,600,
580,600,328,400,
328,400,700,650},mPaint);
}


注意:数组float[] pts的长度必须是4的整倍数,否则,最后一条直线无法绘制。

在MyCanvas的onDraw()方法里调用该方法,效果如下:



4、绘制矩形(有三个方法,结果都一样):drawRect(float left, float top, float right, float bottom, Paint paint)、drawRect(RectF rect, Paint paint)、drawRect(RectF rect, Paint paint)。

private void drawRect(Canvas canvas){
//方法一:
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLACK);
canvas.drawRect(100,100,500,500,mPaint);
//方法二:
Rect rect = new Rect(150,150,450,450);
mPaint.setColor(Color.GREEN);
canvas.drawRect(rect, mPaint);
//方法三:
RectF rectF = new RectF(200,200,400,400);
mPaint.setColor(Color.CYAN);
canvas.drawRect(rectF, mPaint);
}


注意:Rect和RectF两种的区别:最大的区别就是精度不同,Rect是int的,而RectF是float的;两种提供的方法也稍微存在差别,详见官方文档。

在MyCanvas的onDraw()方法里调用该方法,效果如下:



5、绘制圆角矩形(其实既可以画圆角矩形,也可以画椭圆,还有画圆):

drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,Paint paint) 、drawRoundRect(RectF rect, float rx, float ry, Paint paint)。

private void drawRoundRect(Canvas canvas){
//绘制圆角矩形方法一:
RectF rectF1 = new RectF(550,550,880,880);
//两个40的含义:圆角在X、Y两个方向上的半径
canvas.drawRoundRect(rectF1,40,40,mPaint);
//绘制圆角矩形方法二:
mPaint.setColor(Color.WHITE);
canvas.drawRoundRect(600, 600, 850, 850, 40, 40, mPaint);
//画圆(条件:在正方形的基础上绘制才行):
mPaint.setColor(Color.YELLOW);
//圆角在X、Y两个方向上的半径分别为矩形(实际是正方形)长和宽的一半
RectF rectF3 = new RectF(150,150,450,450);
canvas.drawRoundRect(rectF3,150,150,mPaint);

//画椭圆1(条件:在矩形的基础上绘制才行):
mPaint.setColor(Color.GRAY);
RectF rectF4 = new RectF(200,150,400,450);
canvas.drawRoundRect(rectF4,100,150,mPaint);

//画椭圆2(条件:在矩形的基础上绘制才行):
mPaint.setColor(Color.BLACK);
RectF rectF5 = new RectF(200,250,400,350);
canvas.drawRoundRect(rectF5,100,50,mPaint);
}


在MyCanvas的onDraw()方法里调用该方法,效果如下:



6、绘制圆(含圆环):drawCircle(float cx, float cy, float radius, Paint paint)

private void drawCircle(Canvas canvas){
//绘制圆环的两种方式:
//方式一:mPaint画笔style设为描边STROKE,画笔的width加大
//但这样有个缺陷:mPaint的width会均分在圆的内外两侧,
//使得所画出的圆比预期的大;比如下方:
//圆的半径150,mPaint的width = 100,画出来的结果是mPaint的width
//有一半(50)分布在圆半径150的外侧,另一半分布在内侧,
//这样画出来的圆直径比预期大了50(mPaint的width的一半),因此该方法尽可能少用;
mPaint.setColor(Color.GREEN);
mPaint.setStrokeWidth(10);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(200, 200, 100, mPaint);

mPaint.setColor(Color.RED);
//mPaint.setStrokeWidth(1);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(400, 400, 150, mPaint);
//方式二:画两个半径不一样的同心圆
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(400, 400, 100, mPaint);

//画圆
int CircleCenter = widthSize < heightSize ? widthSize : heightSize;
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(8);
mPaint.setColor(Color.BLACK);
canvas.drawCircle(widthSize/2, heightSize/2, (CircleCenter*4)/10, mPaint);
}


在MyCanvas的onDraw()方法里调用该方法,效果如下:



7、绘制圆弧drawArc():drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint);

private void drawArc(Canvas canvas){
//绘制正方形背景
RectF rectF01 = new RectF(50,50,250,250);
mPaint.setColor(Color.parseColor("#00ff00"));
mPaint.setStyle(Paint.Style.FILL);
canvas.drawRect(rectF01, mPaint);
//绘制圆弧
mPaint.setColor(Color.GRAY);
canvas.drawArc(rectF01, 0, 160, false, mPaint);
//绘制长方形背景
RectF rectF02 = new RectF(300,300,700,580);
mPaint.setColor(Color.parseColor("#00ff00"));
canvas.drawRect(rectF02, mPaint);
//绘制圆弧
mPaint.setColor(Color.GRAY);
canvas.drawArc(rectF02, 0, 160, true, mPaint);
}


总结:

1、false:不用圆心,直接是连接圆弧的起点和终点,形成的一个玄弧封闭区域,true:用到圆心,是链接圆弧的起点、中心/圆心、圆弧终点所形成的一个扇形。如下图的上半部分

2、画圆弧,则需要RectF对应的矩形背景为正方形,画椭圆弧,则需要RectF对应的矩形背景为长方形。如下图的下半部分。

在MyCanvas的onDraw()方法里调用该方法,效果如下:



Canvas的基本图形绘制先讲到这里,更深层次的图形绘制我们下一节继续学习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: