您的位置:首页 > 移动开发 > Android开发

Android绘制学习——基础形状

2017-07-20 09:50 351 查看
有些地方待优化处理,这里就没做处理,只是用来学习记录

public class BarChartView extends View {

private Context context;

// 画布的位置
private int XPoint;
private int YPoint;

//刻度长度
private int XScale = 100;
private int YScale = 60;

// x轴y轴的线长
private int XLength;
private int YLength;  // 要减去箭头的长度

// 顶部 底部文字的高度
private int topTextHight = 60;
private int bottomTextHight = 100;

// 设置柱状的高度
private int height = (int)dipToPx(20);
private float betweenHeight;

// 选中的id
private int chooseId = -1;

private int MaxDataSize = XLength / XScale;

private int[] mColors; //对象的颜色
private List<String> text = new ArrayList<>();  // 底部标题
private List<RunStatusBean> infos = new ArrayList<>();  // 每个横条的信息

// 初始化画笔
private Paint paint;
private Paint YPaint;
private Paint YArrowsPaint;
private Paint headPaint;
private Paint dottedPaint;
private Paint datePaint;
private Paint rectanglePaint;
private Paint textInRectangle;
private Paint bottomLinePaint;
private Paint bottomDiscripPain;

public BarChartView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;

// 初始化每一个级别的颜色
mColors = new int[]{Color.parseColor("#F47564"),Color.parseColor("#F2AE6D"),Color.parseColor("#4FC3B8") ,Color.parseColor("#64AFF4")};

// 初始化画笔
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);

// y轴
YPaint = new Paint();
YPaint.setStyle(Paint.Style.STROKE);
YPaint.setAntiAlias(true);
YPaint.setColor(Color.parseColor("#B0B0B0"));

// y轴箭头arrows
YArrowsPaint = new Paint();
YArrowsPaint.setStyle(Paint.Style.STROKE);
YArrowsPaint.setAntiAlias(true);
YArrowsPaint.setColor(Color.parseColor("#B0B0B0"));

// 头部标题
headPaint = new Paint();
headPaint.setTextSize(dipToPx(15));
headPaint.setColor(Color.parseColor("#B0B0B0"));
headPaint.setAntiAlias(true);
headPaint.setTextAlign(Paint.Align.CENTER);

//虚线
dottedPaint = new Paint();
dottedPaint.setStyle(Paint.Style.STROKE);
PathEffect effects = new DashPathEffect(new float[]{5,5,5,5},1);
dottedPaint.setAntiAlias(true);
dottedPaint.setPathEffect(effects);

//日期文字
datePaint = new Paint();
datePaint.setAntiAlias(true);
datePaint.setTextSize(20);
datePaint.setTextAlign(Paint.Align.CENTER);

//矩形
rectanglePaint = new Paint();
rectanglePaint.setAntiAlias(true);
rectanglePaint.setStyle(Paint.Style.FILL);//充满

// 矩形中的文字
textInRectangle = new Paint();
textInRectangle.setTextSize(20);
textInRectangle.setColor(Color.parseColor("#FFFFFF"));
textInRectangle.setAntiAlias(true);
textInRectangle.setTextAlign(Paint.Align.CENTER);

//底部描述文字的矩形
bottomLinePaint = new Paint();
bottomLinePaint.setStyle(Paint.Style.STROKE);
bottomLinePaint.setStrokeWidth(16);
bottomLinePaint.setAntiAlias(true);

// 底部的描述文字
bottomDiscripPain = new Paint();
bottomDiscripPain.setColor(Color.parseColor("#A1A6BB"));
bottomDiscripPain.setAntiAlias(true);
bottomDiscripPain.setTextSize(26);
bottomDiscripPain.setTextAlign(Paint.Align.CENTER);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}

private int measureHeight(int measureSpec) {
int result = Constant.windowHeight / 3; //结果

int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.AT_MOST:  // 子容器可以是声明大小内的任意大小
result = specSize;
break;
case MeasureSpec.EXACTLY:  //父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.  比如EditTextView中的DrawLeft
result = (int)(Constant.windowHeight*(0.4));
break;
case MeasureSpec.UNSPECIFIED:  //父容器对于子容器没有任何限制,子容器想要多大就多大. 所以完全取决于子view的大小
result = specSize;
break;
}
return result;
}

private int measureWidth(int measureSpec) {

int result = Constant.windowWidth; //默认的size

int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.AT_MOST:  // 子容器可以是声明大小内的任意大小
result = specSize;
break;
case MeasureSpec.EXACTLY:  //父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.  比如EditTextView中的DrawLeft
result = specSize;
break;
case MeasureSpec.UNSPECIFIED:  //父容器对于子容器没有任何限制,子容器想要多大就多大. 所以完全取决于子view的大小
result = (text.size() + 2) * XScale;
break;
default:
break;
}
return result;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

//画布宽高的确定
int measuredHeight = getMeasuredHeight();
int measuredWidth = getMeasuredWidth();

//起画点
YPoint = measuredHeight;
XPoint = 60;
// land的y坐标
landY = YPoint - 16;
// y坐标长度
YLength = measuredHeight - bottomTextHight - topTextHight;
XLength = measuredWidth;
// y坐标刻度
YScale = YLength / 5;
MaxDataSize = XLength / XScale;
// 设置柱状的间距
betweenHeight = context.getResources().getDimensionPixelSize(R.dimen.y60);

/*-----------------------------------------------绘制图型--------------------------------------------*/

//画Y轴
canvas.drawLine(XPoint, YPoint - bottomTextHight, XPoint, YPoint - YLength - bottomTextHight, YPaint);

//Y轴箭头
canvas.drawLine(XPoint, YPoint - YLength - bottomTextHight, XPoint - 3, YPoint-YLength - bottomTextHight + 6, YPaint);
canvas.drawLine(XPoint, YPoint - YLength - bottomTextHight, XPoint + 3, YPoint-YLength - bottomTextHight + 6, YPaint);

//画X轴
canvas.drawLine(XPoint, YPoint - bottomTextHight, XPoint + text.size() * XScale, YPoint - bottomTextHight, YPaint);

// 头标题
canvas.drawText("单位:kwh",XPoint + dipToPx(30), topTextHight - 20, headPaint);

//画x轴上的虚线
if(text.size() > 1){
for(int i=0; i<text.size(); i++){
if (i == chooseId){
dottedPaint.setColor(Color.parseColor("#222328"));
}else{
dottedPaint.setColor(Color.parseColor("#B0B0B0"));
}

Path path = new Path();
path.moveTo(XPoint + (i+1) * XScale, YPoint - bottomTextHight);
path.lineTo(XPoint + (i + 1) * XScale, YPoint - YLength - bottomTextHight);
canvas.drawPath(path, dottedPaint);
}
}

// 画x轴下的文字
if(text.size() > 1){
for(int i=0; i<text.size(); i++){
if (i == chooseId){
datePaint.setColor(Color.parseColor("#0786E7"));
}else{
datePaint.setColor(Color.parseColor("#B0B0B0"));
}
canvas.drawText(text.get(i),XPoint + (i+1) * XScale,YPoint -bottomTextHight + 40,datePaint);
}
}

// 画矩形(主要计算出矩形的长度)
for (int i =0; i<infos.size(); i++){
int heightCount = 0;
// 颜色控制
if (infos.get(i).getStatus() == 0){ // 关机
rectanglePaint.setColor(mColors[0]);
heightCount = 1;
}if (infos.get(i).getStatus() == 10){// 正常
rectanglePaint.setColor(mColors[1]);
heightCount = 2;
}if (infos.get(i).getStatus() == 20){// 故障
heightCount = 3;
rectanglePaint.setColor(mColors[2]);
}if (infos.get(i).getStatus() == 30){// 带病运行
heightCount = 4;
rectanglePaint.setColor(mColors[3]);
}

// 画矩形
float left  = ((infos.get(i).getStart()-1) + 0.5f) * XScale + XPoint;   // 拿到月份确定left的位置 和 rigth的位置()
float right  = left + (infos.get(i).getEnd()-infos.get(i).getStart() + 1)*XScale;
float top  = YPoint - bottomTextHight - heightCount * (betweenHeight) - height ;   // 根据状态判断高度
float bottom  = YPoint - bottomTextHight - heightCount * (betweenHeight)  ;   // height 为矩形的高度
RectF oval3 = new RectF(left, top, right, bottom);// 设置个新的长方形
canvas.drawRoundRect(oval3, 10, 10, rectanglePaint);//第二个参数是x半径,第三个参数是y半径

// 画文字
canvas.drawText(infos.get(i).getDesc(), (right - left) / 2 + left, height / 2 + top + 6, textInRectangle);

}

//画底部描述线条
bottomLinePaint.setColor(mColors[3]);

canvas.drawLine(XPoint, landY, XPoint + landWidth, landY, bottomLinePaint);
bottomLinePaint.setColor(mColors[2]);
canvas.drawLine(XPoint + landWidth + landAmong + textWidth(landText[0],26,bottomLinePaint), landY
, XPoint + (landWidth *2) + landAmong + textWidth(landText[0],26,bottomLinePaint), landY, bottomLinePaint);
bottomLinePaint.setColor(mColors[1]);
canvas.drawLine(XPoint + (landWidth *2) + (landAmong *2) + textWidth(landText[0],26,bottomLinePaint)+textWidth(landText[1],26,bottomLinePaint)
, landY, XPoint + (landWidth *3) + (landAmong *2)+ textWidth(landText[0],26,bottomLinePaint)+textWidth(landText[1],26,bottomLinePaint), landY, bottomLinePaint);
bottomLinePaint.setColor(mColors[0]);
canvas.drawLine(XPoint + (landWidth *3) + (landAmong *3)+ 2*textWidth(landText[0],26,bottomLinePaint)+textWidth(landText[1],26,bottomLinePaint)
, landY, XPoint + (landWidth *4) + (landAmong *3)+2*textWidth(landText[0],26,bottomLinePaint)+textWidth(landText[1],26,bottomLinePaint)
, landY, bottomLinePaint);

//画底部描述文字
canvas.drawText(landText[0]
, excursion + XPoint + landWidth + (landAmong + textWidth(landText[0],26,bottomDiscripPain))/ 2
, landY + 8, bottomDiscripPain);
canvas.drawText(landText[1]
, excursion + XPoint + (landWidth * 2) + (landAmong + textWidth(landText[1],26,bottomDiscripPain))/ 2 + (landAmong + textWidth(landText[0],26,bottomDiscripPain))
,landY + 8, bottomDiscripPain);
canvas.drawText(landText[2]
, excursion + XPoint + (landWidth * 3) +(landAmong + textWidth(landText[0],26,bottomDiscripPain))+(landAmong + textWidth(landText[1],26,bottomDiscripPain))+((landAmong + textWidth(landText[2],26,bottomDiscripPain))/2)
,landY +8,bottomDiscripPain);
canvas.drawText(landText[3]
,excursion + XPoint + (landWidth * 4) +(landAmong + textWidth(landText[0],26,bottomDiscripPain))+(landAmong + textWidth(landText[1],26,bottomDiscripPain))+(landAmong + textWidth(landText[2],26,bottomDiscripPain))+((landAmong + textWidth(landText[3],26,bottomDiscripPain))/2)
,landY +8,bottomDiscripPain);
}

private int landWidth = 60;
private int landAmong = 60;
private int excursion = -14;  // land文字向x方向的偏移量
private float landY;
private String [] landText = {"正常","带病运行","故障","关机"};

private float dipToPx(float dip) {
float density = getContext().getResources().getDisplayMetrics().density;
return (int)(dip * density + 0.5f * (dip >= 0 ? 1 : -1));
}

public void setHeight(int height) {    // 设置柱状高度
this.height = height;
}

public void setText(List<String> text) {   // 设置底部标题
this.text = text;
this.invalidate();
}

public void setInfos(List<RunStatusBean> infos) {   // 设置info
this.infos = infos;
this.invalidate();
}

private float textWidth(String string, int size, Paint paint){
paint.setTextSize(size);
float textWidth =paint.measureText(string + "");
return textWidth;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: