双柱状图
今天把上次的柱状图补上,自己也消化消化。先简单的说下绘制的过程,首先获取了屏幕的宽度,分成4份,画四个图片,然后在每个图片的两边画柱状图。然后我加了一个在不同数值范围内为不同颜色。
效果图:
一、柱状图代码:
public class DoubleColumnview extends View { Paint paint, mPaint, linePaint;//画柱状图的画笔和下面文字的画笔以及线的画笔 Activity activity; private Rect mBound;//画上面文字正方形区域 private int mStartWidth, mHeight, mWidth;//文字开始位置,屏幕高度,屏幕宽度 private int mSize = 10;//柱状图宽度 private int btmWith, btmHight;//图片的长度和宽度 private List<Float> list = new ArrayList<>(); private int len;//坐标高度 private int spacing = 20;//图片和线的间距 private int bitmapArray[] = {R.mipmap.ic_launcher, R.mipmap.ic_launcher, R.mipmap.ic_launcher, R.mipmap.ic_launcher}; private List<String> paintColorList = new ArrayList<>();//画笔颜色集合 private Float maxValue = Float.valueOf(1);//最大的值 private int padding = 20;//数字和柱状图的间距 public DoubleColumnview(Context context) { super(context); } public DoubleColumnview(Context context, @Nullable AttributeSet attrs) { super(context, attrs); this.activity = (Activity) context; //柱状图画笔 paint = new Paint(); //文字画笔 mPaint = new Paint(); //上面文字的画笔 linePaint = new Paint(); //设置画笔颜色 paint.setColor(Color.RED); linePaint.setColor(Color.parseColor("#ECEBEB")); //设置画笔抗锯齿 paint.setAntiAlias(true); //线宽 paint.setStrokeWidth(1); linePaint.setStrokeWidth(1); //画字的正方形区域 mBound = new Rect(); } public void setData(List<Databean> listBean) { paintColorList.clear(); list.clear(); maxValue = Float.valueOf(1); setList(listBean); mStartWidth = getWidth() / 5; invalidate(); } private void setList(List<Databean> list) { for (int i = 0; i < list.size(); i++) { if (compare(list.get(i).getLow_value(), list.get(i).getTimecode_avg_result())) { paintColorList.add("#FF9F52"); } else if (compare(list.get(i).getTimecode_avg_result(), list.get(i).getHigh_value())) { paintColorList.add("#C11920"); } else { paintColorList.add("#0073CF"); } this.list.add(Float.parseFloat(list.get(i).getTimecode_avg_result())); maxValue = maxValue > Float.parseFloat(list.get(i).getTimecode_avg_result()) ? maxValue : Float.parseFloat(list.get(i).getTimecode_avg_result()); } } private boolean compare(String value, String avg) { return Float.parseFloat(value) > Float.parseFloat(avg); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); len = height; //设置测量高度和宽度(必须要调用,不然无效果) setMeasuredDimension(width, height); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); // DisplayMetrics dm = new DisplayMetrics(); // activity.getWindowManager().getDefaultDisplay().getMetrics(dm); // mWidth = dm.widthPixels; // mHeight = dm.heightPixels; mWidth = getWidth(); mStartWidth = mWidth / 5; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //画图标 drawImageView(canvas); } private void drawImageView(Canvas canvas) { //为了先测量字所占的正方形空间 mPaint.setTextSize(30); mPaint.setTextAlign(Paint.Align.CENTER); mPaint.setColor(Color.parseColor("#626262")); mPaint.getTextBounds("00.00", 0, "00.00".length(), mBound); maxValue = maxValue * (len - btmHight - spacing) / (len - btmHight - spacing - mBound.height() - padding * 3);//y轴得最大值 for (int i = 1; i < 5; i++) { //画柱状图下的图标 Bitmap bitmap = BitmapFactory.decodeResource(activity.getResources(), bitmapArray[i - 1]); btmWith = bitmap.getWidth(); btmHight = bitmap.getHeight(); canvas.drawBitmap(bitmap, mStartWidth - btmWith / 2, len - btmHight, paint); //画左边柱状图和左边字 paint.setStyle(Paint.Style.FILL); paint.setColor(Color.parseColor(paintColorList.get(2 * i - 2))); RectF rectF = new RectF(); rectF.left = mStartWidth - mBound.width() / 2; rectF.right = mStartWidth - mBound.width() / 2 + mSize; rectF.bottom = len - btmHight - spacing; rectF.top = len - btmHight - spacing - (len - btmHight - spacing) * list.get(2 * i - 2) / maxValue; if (!(list.get(2 * i - 2) == 0.0)) { canvas.drawRoundRect(rectF, 6, 6, paint); canvas.drawText(list.get(2 * i - 2) + "", rectF.left, rectF.top - padding, mPaint); } //画右边柱状图和字 paint.setColor(Color.parseColor(paintColorList.get(2 * i - 1))); rectF.left = mStartWidth + mBound.width() / 2 - mSize; rectF.right = mStartWidth + mBound.width() / 2; rectF.top = len - btmHight - spacing - (len - btmHight - spacing) * list.get(2 * i - 1) / maxValue; if (!(list.get(2 * i - 1) == 0.0)) { canvas.drawRoundRect(rectF, 6, 6, paint); canvas.drawText(list.get(2 * i - 1) + "", rectF.left, rectF.top - padding, mPaint); } mStartWidth += mWidth / 5; } canvas.drawLine(20, len - btmHight - spacing, mWidth - 20, len - btmHight - spacing, linePaint); } }
因为这个柱状图很简单就不多解释了,只要注意几个地方,首先我们都知道坐标原点在屏幕左上角,右边为x正轴,下面为y正轴。
还有就是canvas.drawBitmap(bitmap, mStartWidth - btmWith / 2, len - btmHight, paint);画图片的方法,我这里是用控件高度减去图片的高,因为画的时候它是在y坐标下面开始画(画字的时候好像是从y坐标上面开始画,可以验证下),所以要移上来。
再就是画字的时候,我这里定义了一个正方形 //画字的正方形区域
Rect mBound = new Rect();
通过mPaint.getTextBounds("00.00", 0, "00.00".length(), mBound);方法将话的字塞入正方形mBound,这样我们就能通过mBound的宽高来知道字体的所占的大小。
最后记住我们画柱状图时底部是要减去图片的高度和间距的rectF.bottom = len - btmHight - spacing;
ok了,就这么简单的画出一个柱状图来。
二、贴一下Activity和Bean类:
bean类:
public class Databean { private String low_value; private String timecode_avg_result; private String high_value; public String getLow_value() { return low_value; } public void setLow_value(String low_value) { this.low_value = low_value; } public String getTimecode_avg_result() { return timecode_avg_result; } public void setTimecode_avg_result(String timecode_avg_result) { this.timecode_avg_result = timecode_avg_result; } public String getHigh_value() { return high_value; } public void setHigh_value(String high_value) { this.high_value = high_value; } }Activity代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ DoubleColumnview doubleColumnview; Button btn; List<Databean> list = new ArrayList<>(); Random rand;//随机数 Databean bean; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); doubleColumnview = findViewById(R.id.double_columnview); btn= findViewById(R.id.btn); btn.setOnClickListener(this); rand = new Random(); doubleColumnview.setData(getList()); } public List<Databean> getList(){ list.clear(); for (int i = 0;i < 8;i++) { bean = new Databean(); bean.setTimecode_avg_result(String.valueOf(rand.nextInt(16) + 3)); bean.setLow_value(String.valueOf(4)); bean.setHigh_value(String.valueOf(10)); list.add(bean); } return list; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn: //点击事件中,调用动的方法 doubleColumnview.setData(getList()); break; } } }