最终效果

代码实现

package com.example.chartdemo;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.util.AttributeSet;
import android.view.View;import androidx.annotation.Nullable;import java.util.List;public class BarChartView extends View {public BarChartView(Context context) {this(context,null);}public BarChartView(Context context, @Nullable AttributeSet attrs) {this(context, attrs,0);}public BarChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}private int widthMode;private int heightMode;private int widthSize;private int heightSize;private List<Integer> xItems;//X轴 轴项private String xUnit;//X轴 刻度单位private List<Integer> yItems;//Y轴 轴项private String yUnit;//Y轴 刻度单位private List<Integer> dataList;//数据private List<Integer> dataList2;//数据2private int xStepDistance;//X轴 步距private int yStepDistance;//Y轴 步距@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);widthMode = MeasureSpec.getMode(widthMeasureSpec);heightMode = MeasureSpec.getMode(heightMeasureSpec);widthSize = MeasureSpec.getSize(widthMeasureSpec);heightSize = MeasureSpec.getSize(heightMeasureSpec);initPaint();}private Paint linePaint;private Paint linePaint2;private Paint zhouPaint;private Paint gePaint;private Paint zhouTextPaint;private Paint line1DataTextPaint;private Paint line2DataTextPaint;private void initPaint(){linePaint=new Paint();linePaint.setStyle(Paint.Style.FILL_AND_STROKE);//不加这个不显示linePaint.setColor(Color.RED);linePaint.setStrokeWidth(4);linePaint.setAntiAlias(true);//抗锯齿功能linePaint.setARGB(100,255,0,0); //设置:A代表透明度  B代表红  G代表绿  B代表蓝 (范围:0————255)linePaint.setStrokeJoin(Paint.Join.ROUND);//线条连接处样式linePaint.setStrokeCap(Paint.Cap.ROUND);//设置线头模式/*Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable._l9_line_back);BitmapShader bitmapShader = new BitmapShader(bm, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);linePaint.setShader(bitmapShader);*/linePaint2=new Paint();linePaint2.setStyle(Paint.Style.FILL_AND_STROKE);//不加这个不显示linePaint2.setColor(Color.BLUE);linePaint2.setStrokeWidth(4);linePaint2.setAntiAlias(true);//抗锯齿功能linePaint2.setARGB(100,0,0,255);linePaint2.setStrokeJoin(Paint.Join.ROUND);linePaint2.setStrokeCap(Paint.Cap.ROUND);gePaint=new Paint();gePaint.setColor(Color.parseColor("#A3AFB8"));gePaint.setStyle(Paint.Style.STROKE);//不加这个不显示gePaint.setStrokeWidth(0);gePaint.setAntiAlias(true);//抗锯齿功能PathEffect effects = new DashPathEffect(new float[]{5, 10}, 0);//设置绘制虚线gePaint.setPathEffect(effects);zhouPaint=new Paint();zhouPaint.setColor(Color.BLACK);zhouPaint.setStrokeWidth(4);zhouPaint.setAntiAlias(true);//抗锯齿功能zhouTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);zhouTextPaint.setTextSize(30);line1DataTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);line1DataTextPaint.setARGB(100,255,0,0);line1DataTextPaint.setTextSize(20);line2DataTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);line2DataTextPaint.setARGB(100,0,0,255);line2DataTextPaint.setTextSize(20);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//画 X轴=====================================================================================canvas.drawLine(0,heightSize,widthSize, heightSize,zhouPaint);xStepDistance=widthSize/xItems.size();//X轴 步距值for (int a=0;a<xItems.size();a++){//画刻度canvas.drawLine(xStepDistance*a,heightSize,xStepDistance*a, heightSize-10,zhouPaint);//画格子Path gePath=new Path();gePath.moveTo(xStepDistance*a, heightSize);gePath.lineTo(xStepDistance*a, 0);gePath.close();canvas.drawPath(gePath, gePaint);//绘制X轴 刻度文字canvas.drawText(a==xItems.size()-1 ? xItems.get(a)+"("+xUnit+")" : xItems.get(a)+"", xStepDistance*a-10, heightSize-20, zhouTextPaint);}canvas.drawLine(widthSize,heightSize,widthSize-10,heightSize-10,zhouPaint);//画末尾箭头//画 Y轴=====================================================================================canvas.drawLine(0,0,0, heightSize,zhouPaint);yStepDistance=heightSize/yItems.size();//Y轴 步距值for (int a=0;a<yItems.size();a++){//画刻度if (a!=0)canvas.drawLine(0,heightSize-(yStepDistance*a),10, heightSize-(yStepDistance*a),zhouPaint);//画格子Path gePath=new Path();gePath.moveTo(0, heightSize-(yStepDistance*a));gePath.lineTo(widthSize, heightSize-(yStepDistance*a));gePath.close();canvas.drawPath(gePath, gePaint);//绘制Y轴 刻度文字canvas.drawText(a==yItems.size()-2 ? yItems.get(a)+"("+yUnit+")" : yItems.get(a)+"", 10, heightSize-(yStepDistance*(a+1)), zhouTextPaint);}canvas.drawLine(0,0,10,10,zhouPaint);//画末尾箭头//绘制_数据1===================================================================================double yDataPixel=heightSize/100f; //控件高度的像素个数——与——实际数据的对应关系值 (像素点分给100个数据值)for (int k=0;k<dataList.size();k++){//画方形条canvas.drawRect(xStepDistance*k+20,(int)(heightSize-(dataList.get(k)*yDataPixel)),xStepDistance*k+(xStepDistance/2)-30+20,heightSize,linePaint);canvas.drawText(dataList.get(k)+"", xStepDistance*k+20, (int)(heightSize-(dataList.get(k)*yDataPixel))-20, line1DataTextPaint);}//绘制_数据2===================================================================================for (int k=0;k<dataList2.size();k++){//画方形条canvas.drawRect(xStepDistance*k+(xStepDistance/2),(int)(heightSize-(dataList2.get(k)*yDataPixel)),xStepDistance*k+xStepDistance-30,heightSize,linePaint2);canvas.drawText(dataList2.get(k)+"", xStepDistance*k+(xStepDistance/2), (int)(heightSize-(dataList2.get(k)*yDataPixel))-20, line2DataTextPaint);}}/*** 设置曲线1 数据* @param dataList*/public void setData(List<Integer> dataList){this.dataList=dataList;postInvalidate();}/*** 设置曲线2 数据* @param dataList*/public void setData2(List<Integer> dataList){this.dataList2=dataList;postInvalidate();}/*** 设置X轴参数* @param xList* @param unit 刻度单位*/public void setDataScaleX(List<Integer> xList,String unit){xItems=xList;xUnit=unit;postInvalidate();}/*** 设置Y轴参数* @param yList* @param unit 刻度单位*/public void setDataScaleY(List<Integer> yList,String unit){yItems=yList;yUnit=unit;postInvalidate();}}

使用方法

  1. 在XML中引用
<com.example.chartdemo.BarChartViewandroid:id="@+id/bar_chart"android:background="#EFEFEF"android:layout_margin="20px"android:layout_width="match_parent"android:layout_height="600px" />
  1. 设置参数与数据
List<Integer> dataList=new ArrayList<>();dataList.add(85);dataList.add(90);dataList.add(70);dataList.add(68);dataList.add(50);dataList.add(43);dataList.add(28);dataList.add(21);dataList.add(30);dataList.add(58);dataList.add(70);dataList.add(55);List<Integer> dataList2=new ArrayList<>();dataList2.add(45);dataList2.add(67);dataList2.add(78);dataList2.add(98);dataList2.add(85);dataList2.add(54);dataList2.add(45);dataList2.add(35);dataList2.add(55);dataList2.add(59);dataList2.add(42);dataList2.add(45);List<Integer> xList=new ArrayList<>();xList.add(1);xList.add(2);xList.add(3);xList.add(4);xList.add(5);xList.add(6);xList.add(7);xList.add(8);xList.add(9);xList.add(10);xList.add(11);xList.add(12);List<Integer> yList=new ArrayList<>();yList.add(10);yList.add(20);yList.add(30);yList.add(40);yList.add(50);yList.add(60);yList.add(70);yList.add(80);yList.add(90);yList.add(100);BarChartView bar_chart=(BarChartView) findViewById(R.id.bar_chart);bar_chart.setDataScaleX(xList,"月");bar_chart.setDataScaleY(yList,"件");bar_chart.setData(dataList);bar_chart.setData2(dataList2);//===========动效数据================doBarChartDataList();

东西方法代码

private void doBarChartDataList(){for (int a=0;a<dataList.size();a++){new BarHeartbeat().start(50, a, dataList.get(a), new ActionCallback() {@Overridepublic void toDo(Object o) {List<Integer> list= (List<Integer>) o;dataList.set(list.get(0),list.get(1));bar_chart.setData(dataList);}});}for (int a=0;a<dataList2.size();a++){new BarHeartbeat().start(50, a, dataList2.get(a), new ActionCallback() {@Overridepublic void toDo(Object o) {List<Integer> list= (List<Integer>) o;dataList2.set(list.get(0),list.get(1));bar_chart.setData2(dataList2);}});}}

动效数据辅助类

package com.soface.chartdemo;import android.os.Looper;
import android.os.Message;import java.util.ArrayList;
import java.util.List;/*** 心跳计时器*/
public class BarHeartbeat {//事件标签public final int ACTION_TAG =0xFF;//要回调的接口private ActionCallback thisActionDo;//Handler事件监听器private android.os.Handler mHandler = new android.os.Handler(Looper.getMainLooper()){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what){case ACTION_TAG:List<Integer> list= (List<Integer>) msg.obj;thisActionDo.toDo(list);break;}}};//启动public void start(int countDownTime,int index,int maxNumber,ActionCallback actionDo){thisActionDo=actionDo;for (int a=0;a<=maxNumber;a++){Message msg = mHandler.obtainMessage();msg.what = ACTION_TAG;List<Integer> list=new ArrayList<>();list.add(index);list.add(a);msg.obj=list;mHandler.sendMessageDelayed(msg,countDownTime*a);}};}
package com.soface.chartdemo;public interface ActionCallback {void toDo(Object o);}

Android自定义View绘制条形统计图相关推荐

  1. android自定义弧度按钮,Android 自定义View 绘制六边形设置按钮

    今天逛酷安的时候,发现酷安的设置按钮(截图的右上角),是一个六边形 + 中心圆的图标,所以又是一个自定义View练习对象了.画圆很简单,知道半径即可,而重点就在画出六边形. 酷安截图.png 最终效果 ...

  2. Android自定义View绘制闹钟

    Android自定义View绘制闹钟 本文简单实现了一个闹钟,扩展View,Canvas绘制 效果如下: 代码如下: package com.gaofeng.mobile.clock_demo;imp ...

  3. Android 自定义View绘制电池图标

    /*** @anthor GrainRain* @funcation 自定义View绘制电池* @date 2019/8/27*/ public class DrawBatteryView exten ...

  4. Android自定义View绘制流程

    Android视图层次结构简介 在介绍View绘制流程之前,咱们先简单介绍一下Android视图层次结构以及DecorView,因为View的绘制流程的入口和DecorView有着密切的联系. 我们平 ...

  5. android 自定义View绘制电池电量(电池内带数字显示)

    最新公司需要一个电池内带数字的显示电池电量需求,百度了一下.参考下面这篇文章写的Android自定义View之电池电量显示. 增加了里面电池电量数字显示,还有就是一个屏幕适配.不管屏幕分辨率基本都能适 ...

  6. android画a4矩形,Android自定义View绘制原理:画多大?画在哪?画什么?(三)

    View绘制就好比画画,抛开Android概念,如果要画一张图,首先会想到哪几个基本问题: 画多大? 画在哪? 怎么画? Android绘制系统也是按照这个思路对View进行绘制,上面这些问题的答案分 ...

  7. Android自定义View绘制闪闪发光的文字

    如何实现类似网页效果中闪闪发光的文字,通过自定义View可以实现这一炫酷效果 1.自定义View public class FlickTextView extends TextView {privat ...

  8. Android 自定义View绘制的基本开发流程 Android自定义View(二)

    1 View绘制的过程 View的测量--onMeasure() View的位置确定--onLayout() View的绘制--onDraw() 2 View的测量--onMeasure() Andr ...

  9. Android 自定义View 绘制五角星

    背景 之前写过的App里有评分的功能,而显示评分一般使用系统的RatingBar再加自定义,一切都很完美,但是产品提了一个需求,例如4.6.4.7.5.8分,不要显示为4个星星加一个半星(4.5分), ...

最新文章

  1. 关于TVM的点滴记录
  2. 张文宏在人工智能大会上“泼冷水”:国内疫情基本结束,防控一开始用的全是“人工”!
  3. Socket编程获取服务器时间
  4. 【跃迁之路】【678天】程序员高效学习方法论探索系列(实验阶段435-2018.12.23)...
  5. debian linux u盘安装,使用U盘安装Debian系统图文教程
  6. JAVA md5加密的工具类
  7. Java学习笔记2021.1.9
  8. 牛客-139 I. Substring(后缀数组 or 后缀自动机)
  9. PLSQL连接oracel数据库_用户无法登陆_oci.dll_配置问题
  10. chap01 .net 基本框架介绍
  11. Android保存用户名和密码
  12. linux shell脚本 可以全局使用
  13. java过滤器命名_java 过滤指定后缀文件
  14. Atitit atttilax创造的新概念与模式 xaas xaaK
  15. 中小企业信息网络安全解决方案
  16. App Inventor学习环境搭建
  17. 必看!!!一级建造师各科老师推荐!!!
  18. 大数据能力_大数据基础能力_脑图
  19. ClickHouse函数操作大全
  20. Android刘海屏、水滴屏全面屏适配详解,android开发权威指南

热门文章

  1. C语言结构体作为形参
  2. 环回接口是做什么的?
  3. @[TOC](CDN防御与高防服务器防御的区别
  4. 初学者怎么学java编程
  5. 视频采集卡二次开发(天敏SDK2500+openCV)
  6. informatica使用问题汇总
  7. 《三国群英传2网络版》所有装备掉落查询
  8. 怎么查百度竞价外地排名情况
  9. JSON与fastjson
  10. esxi迁移linux报错device eth0 does not seem tobe present,delaying