基本图形的绘制
public class CanvasLearn extends View {
private Paint mPaint;
public CanvasLearn(Context context) {
this(context, null);
}
public CanvasLearn(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CanvasLearn(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
setCanvasColor(canvas);
// drawPoint(canvas);
// drawLine(canvas);
// drawRectOrRectF(canvas);
// drawRoundRect(canvas);
// drawOval( canvas);
// drawCircle(canvas);
// drawAre(canvas);
}
/**
* 1、初始化画笔
*/
private void initPaint() {
mPaint = new Paint();
mPaint.setStrokeWidth(10);//设置画笔宽度
mPaint.setColor(Color.RED);//设置画笔颜色
mPaint.setStyle(Paint.Style.FILL);//设置画布类型(Fill填充STROKE扫边 FILL_AND_STROKE填充和扫边)
}
/**
* 2、设置画布颜色
*/
private void setCanvasColor(Canvas canvas) {
canvas.drawColor(Color.WHITE);
}
/**
* 3、绘制点及多个点
*/
private void drawPoint(Canvas canvas) {
mPaint.setStrokeCap(Paint.Cap.ROUND);//设置圆角触笔是点变成圆点
mPaint.setColor(Color.BLUE);
canvas.drawPoint(100, 100, mPaint);//绘制一个点
mPaint.setColor(Color.GREEN);//设置画笔颜色区分
canvas.drawPoints(new float[]{500, 200, 500, 400, 500, 600}, mPaint);//根据多个坐标绘制多个点
}
/**
* 4、绘制直线及多个线段
*/
private void drawLine(Canvas canvas) {
mPaint.setColor(Color.BLUE);
canvas.drawLine(100, 100, 300, 100, mPaint);//绘制一条线段(参数是其实点到x、y轴坐标到结束到x、y轴坐标)
mPaint.setColor(Color.GREEN);//设置画笔颜色区分
canvas.drawLines(new float[]{200, 200, 300, 200, 200, 400, 500, 400}, mPaint);
}
/**
* 5、绘制矩形
* Rect与RectF的区别是精度不同,Rect是int型,Rect是float型
*/
private void drawRectOrRectF(Canvas canvas) {
//第一种
canvas.drawRect(100, 100, 800, 200, mPaint);
//第二种
Rect rect = new Rect(100, 300, 800, 400);
canvas.drawRect(rect, mPaint);
//第三种
RectF rectF = new RectF(100, 500, 800, 600);
canvas.drawRect(rectF, mPaint);
}
/**
* 绘制圆角矩形
*/
private void drawRoundRect(Canvas canvas) {
//第一种
RectF rectF = new RectF(100, 100, 800, 400);
canvas.drawRoundRect(rectF, 30, 30, mPaint);
//第二种方法在API21的时候才可以用,建议用第一种
//设置圆弧角度rx>矩形宽度/2(350) ry>矩形高度/2 (200)时都可以画成椭圆
canvas.drawRect(100,600,800,1000,mPaint);
mPaint.setColor(Color.GRAY);
canvas.drawRoundRect(100,600,800,1000,350,250,mPaint);
}
/**
* 绘制椭圆
*/
private void drawOval(Canvas canvas){
//第一种
RectF rectF=new RectF(100,100,800,400);
canvas.drawOval(rectF,mPaint);
//第二种不建议使用21以上才有
canvas.drawOval(100,500,800,900,mPaint);
}
/**
* 绘制一个圆心坐标在(500,500),半径为300 的圆
*/
private void drawCircle(Canvas canvas){
canvas.drawCircle(500,500,300,mPaint);
}
/**
* 绘制圆弧
* 参数介绍startAngle 开始角度 sweepAngle 结束角度 useCenter 是否使用中心
*/
private void drawAre(Canvas canvas){
RectF rectF=new RectF(100,100,500,500);
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF,mPaint);
mPaint.setColor(Color.GREEN);
canvas.drawArc(rectF,0,90,false,mPaint);
RectF rectF1=new RectF(100,600,500,1100);
mPaint.setColor(Color.GRAY);
canvas.drawRect(rectF1,mPaint);
mPaint.setColor(Color.GREEN);
canvas.drawArc(rectF1,0,90,true,mPaint);
}
简单的绘制一个圆饼图
public class PieView extends View {
private int[] datas = {20, 60, 80, 10, 50};//数据
private int[] colors = {Color.BLACK, Color.GREEN, Color.GRAY, Color.RED, Color.BLUE};//颜色
private int mWidth, mHeight; //宽高
private float mRadius; //半径
private RectF rectF;//圆饼图区域
private Paint mPaint = new Paint();//画笔
public PieView(Context context) {
this(context, null);
}
public PieView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public PieView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setAntiAlias(true);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mHeight = h;
mWidth = w;
mRadius = Math.min(mHeight, mWidth) / 2 * 0.8f;
rectF = new RectF(-mRadius, -mRadius, mRadius, mRadius);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mWidth / 2, mHeight / 2);
drawPie(canvas);
}
/**
*绘制圆饼图
*/
private void drawPie(Canvas canvas) {
float sumValues = 0;
for (int i = 0; i < datas.length; i++) {
sumValues += datas[i];
}
float startAngle = 0;//初始角度
for (int i = 0; i < datas.length; i++) {
mPaint.setColor(colors[i]);
float percentage = datas[i] / sumValues ;
float angle=percentage*360;
canvas.drawArc(rectF,startAngle,angle,true,mPaint);
startAngle += angle;
}
}
}
Screenshot_1489053291.png
根据Path图形的绘制
public class PathLearn extends View {
private Paint mPaint;
private int mWidth, mHeight;
public PathLearn(Context context) {
this(context, null);
}
public PathLearn(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public PathLearn(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.GREEN);
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(10);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(mWidth / 2, mHeight / 2);
// canvas.scale(1,-1);//翻转y轴坐标
drawAllPoint(canvas);
drawPathXY(canvas);
// drawPathLine(canvas);
// drawPathRect(canvas);
// drawPathAll(canvas);
// drawPathaddArc(canvas);
}
//------------moveTo、 setLastPoint、 lineTo 和 close-----------------
/**
* 利用path绘制坐标和箭头
* moveTo 设置path起点
* lineTo path直线到终点
*/
private void drawPathXY(Canvas canvas) {
Path mPath = new Path();
mPaint.setStrokeWidth(1);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
//x轴与箭头
mPath.moveTo(-mWidth / 2 * 0.8f, 0);
mPath.lineTo(mWidth / 2 * 0.8f, 0);
mPath.lineTo(mWidth / 2 * 0.8f * 0.95f, -mWidth / 2 * 0.8f * 0.05f);
mPath.moveTo(mWidth / 2 * 0.8f, 0);
mPath.lineTo(mWidth / 2 * 0.8f * 0.95f, mWidth / 2 * 0.8f * 0.05f);
//y轴
mPath.moveTo(0, -mHeight / 2 * 0.8f);
mPath.lineTo(0, mHeight / 2 * 0.8f);
//y轴箭头
mPath.moveTo(mWidth / 2 * 0.8f * 0.05f, mHeight / 2 * 0.8f - mWidth / 2 * 0.8f * 0.05f);
mPath.lineTo(0, mHeight / 2 * 0.8f);
mPath.lineTo(-mWidth / 2 * 0.8f * 0.05f, mHeight / 2 * 0.8f - mWidth / 2 * 0.8f * 0.05f);
canvas.drawPath(mPath, mPaint);
}
/**
* setLastPoint() 重置上一次操作的最后一个点
* close() 方法用于连接当前最后一个点和最初的一个点
*/
private void drawPathLine(Canvas canvas) {
Path mPath = new Path();
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mPath.lineTo(200, 200);
// mPath.moveTo(200,100);
mPath.setLastPoint(200, 100);
mPath.lineTo(200, 0);
mPath.close();
canvas.drawPath(mPath, mPaint);
}
/**
* 用原点和四个端点
*/
private void drawAllPoint(Canvas canvas) {
mPaint.setStrokeWidth(20);
mPaint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawPoints(new float[]{0, 0, mWidth / 2 * 0.8f, 0, -mWidth / 2 * 0.8f, 0, 0, mHeight / 2 * 0.8f, 0, -mHeight / 2 * 0.8f}, mPaint);
}
//------------addCircle() addOval() addRect() addRoundRect() 参数Path.Direction cw 顺时针 ccw 逆时针-----------------
/**
* path绘制矩形
* setLastPoint(-300,300)修改最后点的位置
*/
private void drawPathRect(Canvas canvas) {
Path path = new Path();
// path.addRect(-200, -200, 200, 200, Path.Direction.CW);
path.addRect(-200, -200, 200, 200, Path.Direction.CCW);
// path.setLastPoint(-300,300);
canvas.drawPath(path, mPaint);
}
/**
* patn绘制其他基本图形
* addPath (Path src)将两个Path合并成为一个
* addPath (Path src, float dx, float dy) 进行了位移之后再添加进当前path中
* addPath (Path src, Matrix matrix) 添加到当前path之前先使用Matrix进行变换
*/
private void drawPathAll(Canvas canvas) {
Path path = new Path();
Path path1 = new Path();
Path path2 = new Path();
// mPaint.setStyle(Paint.Style.FILL);
path.addCircle(0, 0, 200, Path.Direction.CW);
// path.setLastPoint(-300,300);
path1.addOval(-300, -200, 300, 200, Path.Direction.CW);
// path.setLastPoint(-300,300);
path2.addRoundRect(-200, -200, 200, 200, 30, 30, Path.Direction.CW);
// path.setLastPoint(-300,300);
path.addPath(path1, 0, -300);
path.addPath(path2, 0, 300);
canvas.drawPath(path, mPaint);
}
//------------addArc与arcTo-----------------
/**
* public void addArc (RectF oval, float startAngle, float sweepAngle)
* public void arcTo (RectF oval, float startAngle, float sweepAngle)
* public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
* oval 圆弧的外切矩形。
* startAngle 开始角度
* sweepAngle 扫过角度(-360 <= sweepAngle <360)
* forceMoveTo 是否强制使用MoveTo
* addArc 直接添加一个圆弧到path中
* arcTo 添加一个圆弧到path,如果圆弧的起点和上次最后一个坐标点不相同,就连接两个点
* forceMoveTo true 将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点
* firceMoveTo false 不移动,而是连接最后一个点与圆弧起点
*/
/**
* 圆弧
*/
private void drawPathaddArc(Canvas canvas) {
Path path = new Path();
path.lineTo(100, -100);
RectF rectF = new RectF(0, -200, 200, 0);
// path.addArc(rectF,0,280);
// path.arcTo(rectF,0,270,false);
path.arcTo(rectF, 0, 270, true);
path.offset(0,300,path);
canvas.drawPath(path, mPaint);
}
//------------isEmpty、 isRect、isConvex、 set 和 offset-----------------
/**
* isEmpty() 判断path中是否包含内容 true-无内容 false-有内容
* isRect() 判断path是否是一个矩形,如果是一个矩形的话,会将矩形的信息存放进参数rect中
* set() 将新的path赋值到现有path
* offset() 就是对path进行一段平移
*/
雷达图的绘制
public class RadarView extends View {
private int count = 8;//数据个数
private float angle = (float) (Math.PI * 2 / count);//每个数据的平均弧度
private float radius; //网络最大半径
private int centerX; //中心X坐标
private int centerY; //中心Y坐标
private String[] titles = {"1", "2", "3", "4", "5", "6","7","8"};
private double[] data = {20, 30, 40, 50, 60, 70,80,90}; //各维度分值
private float maxValues = 100; //数据最大值
private Paint radarPaint = new Paint(); //雷达图画笔
private Paint valuePaint = new Paint(); //网格图画笔
private Paint textPaint = new Paint(); //文本画笔
private Paint xyPaint = new Paint(); //坐标画笔
private int mWidth, mHeight;
public RadarView(Context context) {
this(context, null);
}
public RadarView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RadarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
//初始化数据
private void initView() {
//设置雷达画笔属性
radarPaint.setStyle(Paint.Style.FILL_AND_STROKE);
radarPaint.setColor(Color.GREEN);
radarPaint.setAntiAlias(true);
//设置网格图画笔属性
valuePaint.setStyle(Paint.Style.STROKE);
valuePaint.setColor(Color.BLUE);
valuePaint.setAntiAlias(true);
//设置文本画笔属性
textPaint.setStyle(Paint.Style.FILL);
textPaint.setColor(Color.BLACK);
textPaint.setTextSize(30);
textPaint.setAntiAlias(true);
//设置坐标画笔属性
xyPaint.setColor(Color.RED);
xyPaint.setAntiAlias(true);
xyPaint.setStyle(Paint.Style.STROKE);
xyPaint.setStrokeWidth(4);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
radius = Math.min(mWidth, mHeight) / 2 * 0.8f;
centerY = h / 2;
centerX = w / 2;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.translate(centerX, centerY);
// drawXY(canvas);
drawValues(canvas);
drawCover(canvas);
}
/**
* 画坐标
*/
private void drawXY(Canvas canvas) {
Path mPath = new Path();
//x轴与箭头
mPath.moveTo(-mWidth / 2 * 0.95f, 0);
mPath.lineTo(mWidth / 2 * 0.95f, 0);
mPath.lineTo(mWidth / 2 * 0.95f * 0.95f, -mWidth / 2 * 0.95f * 0.05f);
mPath.moveTo(mWidth / 2 * 0.95f, 0);
mPath.lineTo(mWidth / 2 * 0.95f * 0.95f, mWidth / 2 * 0.95f * 0.05f);
//y轴
mPath.moveTo(0, -mHeight / 2 * 0.95f);
mPath.lineTo(0, mHeight / 2 * 0.95f);
//y轴箭头
mPath.moveTo(mWidth / 2 * 0.95f * 0.05f, mHeight / 2 * 0.95f - mWidth / 2 * 0.95f * 0.05f);
mPath.lineTo(0, mHeight / 2 * 0.95f);
mPath.lineTo(-mWidth / 2 * 0.95f * 0.05f, mHeight / 2 * 0.95f - mWidth / 2 * 0.95f * 0.05f);
canvas.drawPath(mPath, xyPaint);
}
/**
* 绘制网格图和文本
*/
private void drawValues(Canvas canvas) {
Path path = new Path();//多边形path
Path linePath = new Path();//直线Path
float r = radius / count - 1;//设置网格之间的间距
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
float textHeight = (-fontMetrics.ascent - fontMetrics.descent);//文本高度
for (int j = 0; j < count; j++) {
float newR = r * j;
path.reset();
for (int i = 0; i < count; i++) {
float x = (float) (newR * Math.cos(angle * i));
float y = (float) (newR * Math.sin(angle * i));
if(j==count-1){
//绘制直线
linePath.reset();
linePath.moveTo(0, 0);
linePath.lineTo(x, y);
canvas.drawPath(linePath, valuePaint);
}
if (i == 0) {
path.moveTo(newR, 0);
} else {
path.lineTo(x, y);
}
}
path.close();
canvas.drawPath(path, valuePaint);
//绘制文本
float textX = (float) ((radius - r + textHeight / 2) * Math.cos(angle * j));
float textY = (float) ((radius - r + textHeight / 2) * Math.sin(angle * j));
float textWidth = textPaint.measureText(titles[j]);//文本长度
if (j == 0) {
canvas.drawText(titles[j], textX, textY + textHeight / 2, textPaint);
} else if (j == 1) {
canvas.drawText(titles[j], textX - textWidth / 2, textY + textHeight, textPaint);
} else if (j == 2) {
canvas.drawText(titles[j], textX - textWidth / 2, textY + textHeight, textPaint);
} else if (j == 3) {
canvas.drawText(titles[j], textX - textWidth, textY + textHeight / 2, textPaint);
} else if (j == 4) {
canvas.drawText(titles[j], textX - textWidth / 2, textY, textPaint);
} else {
canvas.drawText(titles[j], textX - textWidth / 2, textY, textPaint);
}
}
}
/**
* 绘制覆盖区域
*/
private void drawCover(Canvas canvas) {
Path path=new Path();
float r = radius / count - 1;//设置网格之间的间距
for(int i=0;i<count;i++){
double percent=data[i]/maxValues;
float x = (float) ((radius-r)*Math.cos(angle*i)*percent);
float y = (float) ((radius-r)*Math.sin(angle*i)*percent);
if(i==0){
path.moveTo(x,0);
}else{
path.lineTo(x,y);
}
//绘制小圆点
canvas.drawCircle(x,y,5,radarPaint);
// canvas.drawPoint(x,y,radarPaint);
}
path.close();
radarPaint.setStyle(Paint.Style.STROKE);
canvas.drawPath(path,radarPaint);
//绘制填充区域
radarPaint.setAlpha(105);
radarPaint.setStyle(Paint.Style.FILL_AND_STROKE);
canvas.drawPath(path,radarPaint);
}
}
效果
Screenshot_1489048128.png
Screenshot_1489049585.png
/**
* 根据path绘制饼图
*/
private void drawPathAcr(Canvas canvas) {
float outRadius = mRadius;
outRecF = new RectF(-outRadius, -outRadius, outRadius, outRadius);
float alphaRadius = mRadius * 0.6f;
alphaRecf = new RectF(-alphaRadius, -alphaRadius, alphaRadius, alphaRadius);
float inRadius = mRadius * 0.5f;
inRecF = new RectF(-inRadius, -inRadius, inRadius, inRadius);
if (mDatas.size() == 0) {
return;
}
canvas.rotate(drawStartAngle);
canvas.save();
float startAngle = 0;
for (PieChartBean ben : mDatas) {
float sweepAngle = ben.getPercentage();
outPaht.moveTo(0, 0);
outPaht.arcTo(outRecF, startAngle, sweepAngle);
inPaht.moveTo(0, 0);
inPaht.arcTo(inRecF, startAngle, sweepAngle);
alphaPaht.moveTo(0, 0);
alphaPaht.arcTo(alphaRecf, startAngle, sweepAngle);
pietPaht.op(outPaht, inPaht, Path.Op.DIFFERENCE);
alphaPiePaht.op(alphaPaht, inPaht, Path.Op.DIFFERENCE);
arcPaint.setColor(ben.getPieColor());
canvas.drawPath(pietPaht, arcPaint);
arcPaint.setAlpha(100);
arcPaint.setColor(Color.GRAY);
canvas.drawPath(alphaPiePaht, arcPaint);
outPaht.reset();
inPaht.reset();
alphaPaht.reset();
startAngle += sweepAngle;
}
}
网友评论