package com.xxmassdeveloper.mpchartexample.view;
/**
* @Info 横向多柱图
* @Auth Bello
* @Time 18-3-6 下午6:06
* @Ver
*/
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import java.util.List;
import java.util.regex.Pattern;
/**
* 横向双柱图
*/
public class HorizontalChartView extends View {
private Context context;
/**
* 最大值
*/
private float maxValue;
/**
* 统计项目
*/
private List<HorizontalChartView.Bar> barList;
/**
* 两条统计图之间空间
*/
private int barSpace = 10;
/**
* 各画笔
*/
private Paint leftRectPaint, leftRectTextPaint, circlePaint, circleTextPaint, barPaint, linePaint, textPaint, scoreTextPaint;
/**
* 矩形区域
*/
private RectF barRect;
private RectF leftRect, legendRect;
//左侧描述文字Rect的宽度
private int leftRectWidth;
/**
* 左侧区域宽度
*/
private int leftAreaWidth;
private int barColor1 = Color.parseColor("#FF6633");
private int barColor2 = Color.parseColor("#E0E3E7");
private int textColor = Color.parseColor("#A3A3A3");
private String chartName = "", legend1 = "", legend2 = "", unit1 = "", unit2 = "";
/**
* 是否显示值
*/
private boolean visibleValue = false;
/**
* 计算整个view的高度
*/
private int totalHeight = 0;
public HorizontalChartView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
/**
* 初始化设置
*/
private void init(Context context) {
this.context = context;
leftRectPaint = new Paint();
leftRectPaint.setColor(textColor);
leftRectPaint.setAntiAlias(true);
leftRectTextPaint = new Paint();
leftRectTextPaint.setColor(Color.WHITE);
leftRectTextPaint.setAntiAlias(true);
circlePaint = new Paint();
circlePaint.setColor(barColor2);
circlePaint.setAntiAlias(true);
circleTextPaint = new Paint();
circleTextPaint.setColor(textColor);
circleTextPaint.setAntiAlias(true);
circleTextPaint.setTextSize(45f);
barPaint = new Paint();
barPaint.setColor(barColor2);
barPaint.setAntiAlias(true);
textPaint = new Paint();
textPaint.setColor(textColor);
textPaint.setAntiAlias(true);
barRect = new RectF(0, 0, 0, 0);
leftRect = new RectF(0, 0, 0, 0);
legendRect = new RectF(0, 0, 0, 0);
setBackgroundColor(Color.WHITE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//图表名
textPaint.setTextSize(55f);
textPaint.setColor(Color.BLACK);
canvas.drawText(chartName, 40, 80, textPaint);
//线的宽度占总宽度的0.8,剩余的部分显示分数
float barViewWidth = (float) ((this.getWidth() - leftAreaWidth) * 0.75);
if (isInEditMode()) {
return;
}
//画示例图1
legendRect.left = leftAreaWidth - leftRectWidth - 10;
legendRect.top = 150;
legendRect.right = legendRect.left + 50;
legendRect.bottom = legendRect.top + 30;
barPaint.setColor(barColor1);
canvas.drawRoundRect(legendRect, 5f, 5f, barPaint);
textPaint.setTextSize(32f);
textPaint.setColor(textColor);
canvas.drawText(legend1, legendRect.right + 10, legendRect.bottom - 5, textPaint);
//画示例图2
legendRect.left = legendRect.left + 200;
legendRect.top = 150;
legendRect.right = legendRect.left + 50;
legendRect.bottom = legendRect.top + 30;
barPaint.setColor(barColor2);
canvas.drawRoundRect(legendRect, 5f, 5f, barPaint);
canvas.drawText(legend2, legendRect.right + 10, legendRect.bottom - 5, textPaint);
for (int i = 0; i < barList.size(); i++) {
//左侧文字背景
leftRect.left = leftAreaWidth - leftRectWidth - 10;
leftRect.top = i * leftRectWidth + barSpace * i + 220;
leftRect.right = leftAreaWidth - 10;
leftRect.bottom = leftRect.top + leftRectWidth;
canvas.drawRoundRect(leftRect, 10f, 10f, leftRectPaint);
char[] ts = barList.get(i).getItemName().toCharArray();
if (isInteger(barList.get(i).getItemName())) {
float textSize = leftRectWidth - 20 * 4;
leftRectTextPaint.setTextSize(textSize);
Rect rect = new Rect();
leftRectTextPaint.getTextBounds(barList.get(i).getItemName(), 0, barList.get(i).getItemName().length(), rect);
int width = rect.width();//文字宽
int height = rect.height();//文字高
int tX = (int) (leftRect.left + leftRectWidth / 2 - width / 2 - 8);
//左侧文字
canvas.drawText(String.valueOf(barList.get(i).getItemName()), tX, leftRect.top + height + 50, leftRectTextPaint);
}
for (int j = 0; j < ts.length; j++) {
if (!isInteger(barList.get(i).getItemName())) {
float textSize = (leftRectWidth - 20 * 2) / ts.length - 5;
leftRectTextPaint.setTextSize(textSize);
int tX = (int) (leftRect.left + leftRectWidth / 2 - textSize / 2);
//左侧文字
canvas.drawText(String.valueOf(ts[j]), tX, leftRect.top + textSize * (j + 1) + 10, leftRectTextPaint);
}
//排序的圆背景
canvas.drawCircle(leftRect.left - 60, leftRect.top + leftRectWidth / 2, 40f, circlePaint);
//排序的数字
Paint.FontMetrics fontMetrics = circleTextPaint.getFontMetrics();
float baseLine = -(fontMetrics.ascent + fontMetrics.descent) / 2;
float textWidth = circleTextPaint.measureText((i + 1) + "");
float startX = leftRect.left - 60 - textWidth / 2;
float endY = leftRect.top + leftRectWidth / 2 + baseLine;
canvas.drawText((i + 1) + "", startX, endY, circleTextPaint);
}
//第一柱
barRect.left = leftAreaWidth;
barRect.top = i * leftRectWidth + barSpace * i + 220;
barRect.right = (int) (barViewWidth * (barList.get(i).getScore() / maxValue)) + leftAreaWidth;
barRect.bottom = barRect.top + leftRectWidth / 2 - barSpace / 2;
barPaint.setColor(barColor1);
canvas.drawRoundRect(barRect, 10f, 10f, barPaint);
//第一柱的值
if (visibleValue) {
textPaint.setTextSize(45f);
textPaint.setColor(barColor1);
canvas.drawText(barList.get(i).getScore() + unit1, barRect.right + 15, barRect.bottom - 20, textPaint);
}
//第二柱
barRect.left = leftAreaWidth;
barRect.top = barRect.bottom + barSpace;
barRect.right = (int) (barViewWidth * (barList.get(i).getScore2() / maxValue)) + leftAreaWidth;
barRect.bottom = barRect.top + leftRectWidth / 2 - barSpace / 2;
barPaint.setColor(barColor2);
canvas.drawRoundRect(barRect, 10f, 10f, barPaint);
//第二柱的值
if (visibleValue) {
textPaint.setColor(barColor2);
canvas.drawText(barList.get(i).getScore2() + unit2, barRect.right + 15, barRect.bottom - 20, textPaint);
}
}
// canvas.drawText(String.valueOf(maxValue), leftAreaWidth + barViewWidth - textPaint.measureText(String.valueOf(maxValue)) / 2,
// barSpace, textPaint);
// canvas.drawText("0(分)", leftAreaWidth - betweenMargin - textPaint.measureText("0(分)"), barSpace, textPaint);
// canvas.drawLine(leftAreaWidth, 0, leftAreaWidth, this.getHeight(), linePaint);
}
public boolean isVisibleValue() {
return visibleValue;
}
public void setVisibleValue(boolean visibleValue) {
this.visibleValue = visibleValue;
}
/**
* 设置统计项目列表
*
* @param legend1
* @param legend2
* @param chartName
* @param barList
*/
public void setBarList(String chartName, String legend1, String legend2, String unit1, String unit2, List<HorizontalChartView.Bar>
barList) {
this.chartName = chartName;
this.legend1 = legend1;
this.legend2 = legend2;
this.barList = barList;
this.unit1 = unit1;
this.unit2 = unit2;
if (barList == null) {
throw new RuntimeException("BarChartView.setItems(): the param items cannot be null.");
}
if (barList.size() == 0) {
return;
}
maxValue = barList.get(0).getScore();
for (Bar bar : barList) {
if (bar.getScore() > maxValue) {
maxValue = bar.getScore();
}
if (bar.getScore2() > maxValue) {
maxValue = bar.getScore2();
}
}
invalidate();
}
public static class Bar {
float score;
float score2;
String itemName;
public Bar(float score, float score2, String itemName) {
this.score = score;
this.score2 = score2;
this.itemName = itemName;
}
public float getScore() {
return score;
}
public void setScore(float score) {
this.score = score;
}
public float getScore2() {
return score2;
}
public void setScore2(float score2) {
this.score2 = score2;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
leftAreaWidth = (int) (width * 0.3);
leftRectWidth = (int) (leftAreaWidth * 0.5);
totalHeight = (220 + (leftRectWidth + barSpace) * barList.size());
int height = getMySize(totalHeight, heightMeasureSpec);
setMeasuredDimension(widthMeasureSpec, height);
}
private int getMySize(int defaultSize, int measureSpec) {
int mySize = defaultSize;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
switch (mode) {
case MeasureSpec.UNSPECIFIED: {//如果没有指定大小,就设置为默认大小
mySize = defaultSize;
break;
}
case MeasureSpec.AT_MOST: {//如果测量模式是最大取值为size
//我们将大小取最大值,你也可以取其他值
mySize = size;
break;
}
case MeasureSpec.EXACTLY: {//如果是固定的大小,那就不要去改变它
mySize = size;
break;
}
}
return mySize;
}
/*方法二:推荐,速度最快
* 判断是否为整数
* @param str 传入的字符串
* @return 是整数返回true,否则返回false
*/
public static boolean isInteger(String str) {
Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
return pattern.matcher(str).matches();
}
}