一 简介
1.1 图表用于直观的分析数据的分布情况,用于对比数据的大小和趋势。
1.2 图表的类型也非常多,常见的有折线,柱状,饼状,其它的有面积,散点,股价,雷达,仪表盘,漏斗等。
1.3 Android也有非常优秀的图表库,比如MPAndroidChart,hellocharts-android,AnyChart-Android等,其中MPAndroidChart目前使用量第一,优势在于自定义程度非常高,而且配置参数非常多,通过配置就能基本上实现所有的图表。
二 MPAndroidChart图表案例,柱状图
2.1 效果
2.2 添加 MPAndroidChart 依赖库
repositories {maven { url 'https://jitpack.io' }
}dependencies {implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
}
2.4 xml添加柱状图组件BarChart
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><com.github.mikephil.charting.charts.BarChartandroid:id="@+id/chart1"android:layout_width="match_parent"android:layout_height="300dp" /></FrameLayout>
2.5 设置图表配置和数据
public class BarActivity extends AppCompatActivity {private BarChart chart;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_bar_chart);//获取柱状图控件chart = findViewById(R.id.chart1);//初始化柱状图控件initBarChart();}/*** 初始化柱状图控件*/private void initBarChart(){// 是否显示描述chart.getDescription().setEnabled(false);// 如果图表中显示的条目超过60个,则不会显示任何值chart.setMaxVisibleValueCount(60);// 只能分别在x轴和y轴上进行缩放chart.setPinchZoom(false);// 阴影chart.setDrawBarShadow(false);// 是否绘制背景线chart.setDrawGridBackground(false);// x坐标绘制XAxis xAxis = chart.getXAxis();// x坐标位置xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);// x坐标线xAxis.setDrawGridLines(false);//Y轴左边第1条线chart.getAxisLeft().setDrawGridLines(false);// 添加一个漂亮平滑的动画chart.animateY(1500);// 是否绘制图例chart.getLegend().setEnabled(false);//设置数据setData();}/*** 设置数据*/private void setData(){//柱状数量 相当于二位数组的 二级数据ArrayList<BarEntry> values = new ArrayList<>();for (int i = 0; i < 10; i++) {float multi = (10 + 1);float val = (float) (Math.random() * multi) + multi / 3;values.add(new BarEntry(i, val));}// 柱状分类,相当于二位数组的 一级数据BarDataSet set1 = new BarDataSet(values, "Data Set");set1.setColors(ColorTemplate.VORDIPLOM_COLORS);set1.setDrawValues(false);// 图表数据集合ArrayList<IBarDataSet> dataSets = new ArrayList<>();dataSets.add(set1);// 填充图表数据BarData data = new BarData(dataSets);chart.setData(data);chart.setFitBars(true);// 刷新图表UIchart.invalidate();}
三 饼状图表
3.1 效果
3.2 xml里面增加饼状组件PieChart
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><com.github.mikephil.charting.charts.PieChartandroid:id="@+id/chart1"android:layout_width="match_parent"android:layout_height="300dp" />
</LinearLayout>
3.3 Activity里面配置参数和数据
public class PieCharActivity extends Activity {private PieChart chart;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_pie_chart);//饼状图控件chart = findViewById(R.id.chart1);//初始化饼状组件initChart();}private void initChart(){//是否用于百分比数据chart.setUsePercentValues(true);chart.getDescription().setEnabled(false);chart.setExtraOffsets(5, 10, 5, 5);chart.setDragDecelerationFrictionCoef(0.95f);//设置中间文本的字体//chart.setCenterTextTypeface(tfLight);//chart.setCenterText(generateCenterSpannableText());//是否绘制中心圆形区域和颜色chart.setDrawHoleEnabled(true);chart.setHoleColor(Color.WHITE);//是否绘制中心边透明区域chart.setTransparentCircleColor(Color.WHITE);chart.setTransparentCircleAlpha(110);//绘制中中心圆,和圆边的边框大小chart.setHoleRadius(58f);chart.setTransparentCircleRadius(61f);//是否绘制中心区域文字chart.setDrawCenterText(true);//默认旋转角度chart.setRotationAngle(0);//通过触摸启用图表的旋转chart.setRotationEnabled(true);//触摸进行高亮的突出设置chart.setHighlightPerTapEnabled(true);//设置单位// chart.setUnit(" €");// chart.setDrawUnitsInChart(true);//添加选择侦听器chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {@Overridepublic void onValueSelected(Entry e, Highlight h) {//选中的扇页}@Overridepublic void onNothingSelected() {//未选中的扇页}});//动画chart.animateY(1400, Easing.EaseInOutQuad);// chart.spin(2000, 0, 360);//图例Legend l = chart.getLegend();l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);l.setOrientation(Legend.LegendOrientation.VERTICAL);l.setDrawInside(false);l.setXEntrySpace(7f);l.setYEntrySpace(0f);l.setYOffset(0f);//标签样式chart.setEntryLabelColor(Color.WHITE);//chart.setEntryLabelTypeface(tfRegular);chart.setEntryLabelTextSize(12f);//设置数据setData();}//设置数据private void setData() {//二维数据的二级数据ArrayList<PieEntry> entries = new ArrayList<>();//new PieEntry(数值,描述,图标icon)第一个entries.add(new PieEntry(40.0f, "数据1", null));entries.add(new PieEntry(20.0f, "数据2", null));entries.add(new PieEntry(30.0f, "数据3", null));entries.add(new PieEntry(10.0f, "数据4", null));//二维数据的一级数据PieDataSet dataSet = new PieDataSet(entries, "Election Results");//数据配置,是否绘制图标dataSet.setDrawIcons(false);//扇页之间的空白间距dataSet.setSliceSpace(3f);//图标偏移dataSet.setIconsOffset(new MPPointF(0, 40));dataSet.setSelectionShift(5f);//添加颜色集合,ArrayList<Integer> colors = new ArrayList<>();//colors.add(ColorTemplate.LIBERTY_COLORS[0]);colors.add(Color.parseColor("#3790A2"));colors.add(Color.parseColor("#37F0A2"));colors.add(Color.parseColor("#49DBEE"));colors.add(Color.parseColor("#43C088"));dataSet.setColors(colors);//dataSet.setSelectionShift(0f);//设置图表数据PieData data = new PieData(dataSet);data.setValueFormatter(new PercentFormatter());data.setValueTextSize(11f);data.setValueTextColor(Color.WHITE);//data.setValueTypeface(tfLight);chart.setData(data);//撤消所有高光chart.highlightValues(null);//刷新图表UIchart.invalidate();}
}
四 折线图
4.1 效果
4.2 xml添加折线组件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><com.github.mikephil.charting.charts.PieChartandroid:id="@+id/chart1"android:layout_width="match_parent"android:layout_marginTop="20dp"android:layout_height="300dp" />
</LinearLayout>
4.3 Activity配置折现参数和数据
public class LineChartActivity extends Activity {private LineChart chart;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_line_chart);//折线图表组件chart = findViewById(R.id.chart1);//初始化图表initChart();}//初始化图表private void initChart(){//点击监听//chart.setOnChartValueSelectedListener(this);//绘制网格线chart.setDrawGridBackground(false);//描述文本chart.getDescription().setEnabled(false);//是否可以触摸chart.setTouchEnabled(true);//启用缩放和拖动chart.setDragEnabled(true);chart.setScaleEnabled(true);// 如果禁用,可以分别在x轴和y轴上进行缩放chart.setPinchZoom(true);//设置背景色// chart.setBackgroundColor(Color.GRAY);//创建自定义MarkerView(扩展MarkerView)并指定布局//MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view);//mv.setChartView(chart); // For bounds control//chart.setMarker(mv); // Set the marker to the chart//配置x坐标数据XAxis xl = chart.getXAxis();xl.setAvoidFirstLastClipping(true);xl.setAxisMinimum(0f);//配置y坐标左边数据YAxis leftAxis = chart.getAxisLeft();leftAxis.setInverted(true);leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)//关闭y坐标右边数据YAxis rightAxis = chart.getAxisRight();rightAxis.setEnabled(false);//抑制最大比例因子// chart.setScaleMinima(3f, 3f);//将视图居中到图表中的特定位置// chart.centerViewPort(10, 50);//图例Legend l = chart.getLegend();//修改图例l.setForm(Legend.LegendForm.LINE);setData();}private void setData() {//二维数组 一级数据ArrayList<Entry> entries = new ArrayList<>();for (int i = 0; i < 10; i++) {float xVal = (i+1);float yVal = (float) (Math.random() * 100);entries.add(new Entry(xVal, yVal));}//通过x坐标值排序Collections.sort(entries, new EntryXComparator());//二维数组 二级数据LineDataSet set1 = new LineDataSet(entries, "DataSet 1");//折现的宽度合折点的半径大小set1.setLineWidth(1.5f);set1.setCircleRadius(4f);//使用数据集创建数据对象LineData data = new LineData(set1);chart.setData(data);//刷新绘图chart.invalidate();}}
五 进阶饼状图和折线图,配置双折线和渐变区域
5.1 效果图
5.2 xml布局添加饼状和折线组件
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Viewandroid:id="@+id/view_statues"android:layout_width="match_parent"android:layout_height="0dp"android:background="@color/white" /><RelativeLayoutandroid:id="@+id/v_title_layout"android:layout_width="match_parent"android:layout_height="44dp"android:background="@color/white"><ImageViewandroid:id="@+id/v_back"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_marginLeft="10dp"android:paddingLeft="10dp"android:paddingRight="10dp"android:src="@mipmap/ic_back" /><LinearLayoutandroid:id="@+id/v_date"android:layout_width="wrap_content"android:layout_height="34dp"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_marginRight="20dp"android:background="@drawable/shape_bg_welcom_gradient"android:gravity="center"android:paddingLeft="7dp"android:paddingRight="7dp"><TextViewandroid:id="@+id/tv_date"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="2022.05"android:textColor="@color/white"android:textSize="16sp" /><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/down_white" /></LinearLayout></RelativeLayout><androidx.core.widget.NestedScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="20dp"android:layout_marginTop="7dp"android:gravity="center_vertical"android:text="統計"android:textColor="@color/color_text_title"android:textSize="20sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="20dp"android:layout_marginTop="18dp"android:gravity="center_vertical"android:text="記錄"android:textColor="@color/color_text_title"android:textSize="20sp" /><FrameLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="18dp"android:paddingLeft="20dp"android:paddingRight="20dp"><com.github.mikephil.charting.charts.PieChartandroid:id="@+id/v_pie_chart"android:layout_width="match_parent"android:layout_height="228dp" /></FrameLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:paddingLeft="20dp"android:paddingRight="20dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:drawableLeft="@drawable/shape_circle_tingji1"android:drawablePadding="10dp"android:gravity="center_vertical"android:text="掃碼"android:textColor="@color/color_text_title"android:textSize="16sp" /><Viewandroid:layout_width="0dp"android:layout_height="1dp"android:layout_weight="1" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:drawableLeft="@drawable/shape_circle_tingji2"android:drawablePadding="10dp"android:gravity="center_vertical"android:text="歷史價格"android:textColor="@color/color_text_title"android:textSize="16sp" /><Viewandroid:layout_width="0dp"android:layout_height="1dp"android:layout_weight="1" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:drawableLeft="@drawable/shape_circle_tingji3"android:drawablePadding="10dp"android:gravity="center_vertical"android:text="個性二維碼"android:textColor="@color/color_text_title"android:textSize="16sp" /></LinearLayout><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="20dp"android:layout_marginTop="20dp"android:gravity="center_vertical"android:text="訂單"android:textColor="@color/color_text_title"android:textSize="20sp" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:paddingLeft="20dp"android:paddingRight="20dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:drawableLeft="@drawable/shape_circle_order1"android:drawablePadding="8dp"android:gravity="center_vertical"android:text="未購買"android:textColor="@color/color_text_title"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="20dp"android:drawableLeft="@drawable/shape_circle_order2"android:drawablePadding="8dp"android:gravity="center_vertical"android:text="已購買"android:textColor="@color/color_text_title"android:textSize="16sp" /></LinearLayout><FrameLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:paddingLeft="20dp"android:paddingRight="10dp"android:layout_marginBottom="20dp"><com.github.mikephil.charting.charts.LineChartandroid:id="@+id/v_line_chart"android:layout_width="match_parent"android:layout_height="228dp" /></FrameLayout></LinearLayout></androidx.core.widget.NestedScrollView></LinearLayout></layout>
5.4 Activity配置数据
public abstract class BaseActivity<Binding extends ViewDataBinding> extends AppCompatActivity {private ActivityBaseBinding activityBaseBinding;public Binding mDataBinding;public Activity mContext;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);mContext = this;activityBaseBinding=DataBindingUtil.setContentView(this, R.layout.activity_base);initLayoutView();}private void initLayoutView() {activityBaseBinding.vBack.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {finish();}});StatuesBarUtils.setAppBar(this, true, R.color.white);mDataBinding = DataBindingUtil.inflate(getLayoutInflater(), getLayoutId(),activityBaseBinding.vContainer, true);initData();}public void hideTitleLayout() {StatuesBarUtils.setNoAppBar(this, true);activityBaseBinding.vTitleLayout.setVisibility(View.GONE);}public void hideTitleLayout(View viewStatues) {StatuesBarUtils.setNoAppBar(this, true);activityBaseBinding.vTitleLayout.setVisibility(View.GONE);LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) viewStatues.getLayoutParams();layoutParams.height = StatuesBarUtils.getStatusHeight(mContext);viewStatues.setLayoutParams(layoutParams);}public void setTitleText(String text) {activityBaseBinding.vHeadTitle.setText(text);}protected abstract int getLayoutId();public abstract void initData();
}
public class StatisticsActivity extends BaseActivity<ActivityStatisticsBinding> {private LineChart chart;//折线图private PieChart pieChart;//饼状图@Overrideprotected int getLayoutId() {return R.layout.activity_statistics;}@Overridepublic void initData() {hideTitleLayout(mDataBinding.viewStatues);mDataBinding.vBack.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {finish();}});mDataBinding.vDate.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {initDatePicker();}});//饼状图组件pieChart = mDataBinding.vPieChart;initChartPie();//折线图组件chart = mDataBinding.vLineChart;initLineChar();}//初始化饼状图private void initChartPie() {//百分比数据pieChart.setUsePercentValues(true);//关闭描述pieChart.getDescription().setEnabled(false);//设置四周间距pieChart.setExtraOffsets(5, 10, 5, 5);//拖动旋转摩擦系数pieChart.setDragDecelerationFrictionCoef(0.95f);//中间文本pieChart.setCenterText("");//半透明区域pieChart.setTransparentCircleColor(Color.WHITE);pieChart.setTransparentCircleAlpha(110);//中间白色圆环半径pieChart.setHoleRadius(58f);pieChart.setDrawHoleEnabled(false);pieChart.setTransparentCircleRadius(61f);pieChart.setDrawCenterText(true);//旋转角度pieChart.setRotationAngle(90);//是否可以触摸旋转pieChart.setRotationEnabled(true);pieChart.setHighlightPerTapEnabled(true);//单位//chart.setUnit(" €");//chart.setDrawUnitsInChart(true);//选中监听//chart.setOnChartValueSelectedListener(this);pieChart.setEntryLabelColor(Color.BLACK);//动画pieChart.animateY(700, Easing.EaseInOutQuad);//chart.spin(2000, 0, 360);//图例Legend l = pieChart.getLegend();l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);l.setOrientation(Legend.LegendOrientation.VERTICAL);l.setDrawInside(false);l.setEnabled(false);//设置饼状图数据setPieData();}//设置饼状图数据private void setPieData() {//二维数组 二级数据ArrayList<PieEntry> entries = new ArrayList<>();entries.add(new PieEntry(51.0f, "掃碼", null));entries.add(new PieEntry(23.0f, "歷史價格", null));entries.add(new PieEntry(39.0f, "個性二維碼", null));//二维数组 一级数据PieDataSet dataSet = new PieDataSet(entries, "Election Results");//扇页之间间距//dataSet.setSliceSpace(3f);//dataSet.setSelectionShift(5f);//添加颜色ArrayList<Integer> colors = new ArrayList<>();colors.add(Color.parseColor("#37F0A2"));colors.add(Color.parseColor("#49DBEE"));colors.add(Color.parseColor("#43C088"));dataSet.setColors(colors);//设置百分比线的位置,分别是拐角,长线和短线dataSet.setValueLinePart1OffsetPercentage(80.f);dataSet.setValueLinePart1Length(0.3f);dataSet.setValueLinePart2Length(0.7f);//设置百分比线是在圆盘上还是圆盘外//dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);//设置饼状数据PieData data = new PieData(dataSet);data.setValueFormatter(new PercentFormatter());//data.setValueFormatter(new AssetsFormatter());data.setValueTextSize(11f);data.setValueTextColor(Color.BLACK);pieChart.setData(data);//取消高亮pieChart.highlightValues(null);//刷新UIpieChart.invalidate();}//初始化折线配置private void initLineChar() {//选中监听//chart.setOnChartValueSelectedListener(this);//是否开启描述chart.getDescription().setEnabled(false);chart.setDescription(null);//是否支持手势点击chart.setTouchEnabled(true);//拖动摩擦系数,即拖动流畅度chart.setDragDecelerationFrictionCoef(0.9f);//是否可以缩放和拖拽chart.setDragEnabled(false);chart.setScaleEnabled(false);chart.setDrawGridBackground(false);chart.setHighlightPerDragEnabled(true);//如果禁用,可以分别在x轴和y轴上进行缩放chart.setPinchZoom(true);//背景颜色chart.setBackgroundColor(Color.TRANSPARENT);//动画chart.animateX(700);//无数据文案chart.setNoDataText("暫無數據");//四周间距//chart.setViewPortOffsets(10, 0, 0,10);//x轴配置XAxis xAxis = chart.getXAxis();//xAxis.setTypeface(tfLight);xAxis.setTextSize(11f);xAxis.setTextColor(Color.parseColor("#999999"));xAxis.setDrawGridLines(false);xAxis.setDrawAxisLine(false);//x轴刻度位置xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);xAxis.setAxisLineColor(Color.parseColor("#ECECEC"));xAxis.setGridColor(Color.parseColor("#ECECEC"));//Y轴左边线配置YAxis leftAxis = chart.getAxisLeft();//leftAxis.setTypeface(tfLight);leftAxis.setTextColor(Color.parseColor("#999999"));leftAxis.setAxisMaximum(200f);leftAxis.setAxisMinimum(0f);leftAxis.setDrawGridLines(true);leftAxis.setGranularityEnabled(false);leftAxis.setAxisLineColor(Color.TRANSPARENT);leftAxis.setGridColor(Color.parseColor("#ECECEC"));//禁用y轴右边线YAxis rightAxis = chart.getAxisRight();rightAxis.setEnabled(false);//图例Legend legend = chart.getLegend();legend.setEnabled(false);//设置折线数据setLineData();}//设置折线数据private List<Entry> allEntryList = new ArrayList<>();private void setLineData() {//二维数组 二级数据1ArrayList<Entry> values1 = new ArrayList<>();values1.add(new Entry(0, 12f));values1.add(new Entry(1, 29f));values1.add(new Entry(2, 19f));values1.add(new Entry(3, 25f));values1.add(new Entry(4, 18f));//二维数组 二级数据2ArrayList<Entry> values2 = new ArrayList<>();values2.add(new Entry(0, 16f));values2.add(new Entry(1, 33f));values2.add(new Entry(2, 11f));values2.add(new Entry(3, 20f));values2.add(new Entry(4, 26f));List<LineDataSet> lineDataSetList = new ArrayList<>();//第一条折线的数据if (values1.size() > 0) {LineDataSet set1 = new LineDataSet(values1, null);//创建数据集并为其指定类型set1.setAxisDependency(YAxis.AxisDependency.LEFT);//折线颜色set1.setColor(Color.parseColor("#35E5FF"));//折线宽set1.setLineWidth(2f);//折点是否填充,即实心还是空心set1.setFillAlpha(80);//高亮颜色set1.setHighLightColor(Color.TRANSPARENT);//绘制圆形孔set1.setDrawCircleHole(false);//折点颜色set1.setCircleColor(Color.parseColor("#FFBD02"));//折点半径set1.setCircleRadius(3f);//格式化折点数据//set1.setFillFormatter(new MyFillFormatter(0f));//是否绘制水平方向的高亮线set1.setDrawHorizontalHighlightIndicator(false);//该条折线是否可见//set1.setVisible(false);//绘制平面填充区域set1.setDrawFilled(true);if (Utils.getSDKInt() >= 18) {//仅在api级别18及以上版本上支持drawinables,渐变色drawableDrawable drawable = ContextCompat.getDrawable(this, R.drawable.line_fade_1);set1.setFillDrawable(drawable);} else {//纯色set1.setFillColor(Color.parseColor("#35E5FF"));}//添加所有折线的集合lineDataSetList.add(set1);}//第二条折线的数据if (values2.size() > 0) {LineDataSet set2 = new LineDataSet(values2, null);set2.setAxisDependency(YAxis.AxisDependency.RIGHT);set2.setColor(Color.parseColor("#FFBD02"));set2.setCircleColor(Color.parseColor("#35E5FF"));set2.setLineWidth(2f);set2.setCircleRadius(3f);set2.setFillAlpha(80);set2.setDrawFilled(true);set2.setDrawCircleHole(false);set2.setHighLightColor(Color.TRANSPARENT);if (Utils.getSDKInt() >= 18) {//仅在api级别18及以上版本上支持drawinables,渐变色drawableDrawable drawable = ContextCompat.getDrawable(this, R.drawable.line_fade_2);set2.setFillDrawable(drawable);} else {set2.setFillColor(Color.parseColor("#FFBD02"));}lineDataSetList.add(set2);}//设置总数据if (lineDataSetList.size() > 0) {LineDataSet[] lineDataSets = lineDataSetList.toArray(new LineDataSet[lineDataSetList.size()]); LineData data = new LineData(lineDataSets);data.setValueTextColor(Color.TRANSPARENT);data.setValueTextSize(9f);//这是折线数据chart.setData(data);//设置x轴值chart.getXAxis().setLabelCount(values1.size(), true);chart.getXAxis().setValueFormatter(new ValueFormatter() {@Overridepublic String getFormattedValue(float value) {String[] monthArray = new String[]{"一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"};int index = (int) value;return monthArray[index];}});//设置Y最大值allEntryList.clear();allEntryList.addAll(values1);allEntryList.addAll(values2);List<Float> floatYList = new ArrayList<>();for (Entry entry : allEntryList) {floatYList.add(entry.getY());}if (allEntryList.size() > 0) {//设置Y轴最大设置范围和格式化数据chart.getAxisLeft().setAxisMaximum(Collections.max(floatYList) + 10);chart.getAxisLeft().setValueFormatter(new ValueFormatter() {@Overridepublic String getFormattedValue(float v) {return String.valueOf(v);}});}} else {chart.setData(null);}//刷新图表chart.invalidate();}
}
六 折线图进阶,添加平均值限制线
6.1 效果图
6.2 直接上配置吧
package com.xixia.chart;import android.content.Context;
import android.graphics.Color;import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IndexAxisValueFormatter;
import com.github.mikephil.charting.utils.ColorTemplate;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;/*** @ClassName LineChartViewUtils* @Description TODO 内容* @Author biekangdong* @CreateDate 2023/5/25 21:28* @Version 1.0* @UpdateDate 2023/5/25 21:28* @UpdateRemark 更新说明*/
public class LineChartViewUtils {private Context context;public LineChartViewUtils(Context context) {this.context=context;}//配置折线数据private void initChart(LineChart chart) {//关闭描述chart.getDescription().setEnabled(false);//关闭高亮chart.setHighlightPerDragEnabled(false);//关闭图例Legend l = chart.getLegend();l.setEnabled(false);//x轴数据XAxis xAxis = chart.getXAxis();xAxis.setPosition(XAxis.XAxisPosition.BOTH_SIDED);xAxis.setTextSize(10f);xAxis.setTextColor(Color.parseColor("#999999"));xAxis.setDrawAxisLine(true);xAxis.setAxisLineColor(Color.parseColor("#DADADA"));xAxis.setAxisLineWidth(0.5f);xAxis.setDrawGridLines(true);xAxis.setGridColor(Color.parseColor("#DADADA"));xAxis.setGridLineWidth(0.5f);chart.getXAxis().setValueFormatter(indexAxisValueFormatter);//Y轴数据YAxis leftAxis = chart.getAxisLeft();leftAxis.setEnabled(true);leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);leftAxis.setTextColor(Color.TRANSPARENT);leftAxis.setDrawGridLines(false);leftAxis.setDrawAxisLine(false);//最小Y轴//leftAxis.setAxisMinimum(0f);//最大Y轴//leftAxis.setAxisMaximum(170f);//Y轴偏移//leftAxis.setYOffset(-9f);//关闭右边Y轴数值显示YAxis rightAxis = chart.getAxisRight();rightAxis.setEnabled(true);rightAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);rightAxis.setTextColor(Color.TRANSPARENT);rightAxis.setDrawGridLines(false);rightAxis.setDrawAxisLine(false);}int position = 0;//时间格式化SimpleDateFormat mFormatHour = new SimpleDateFormat("HH:mm", Locale.ENGLISH);SimpleDateFormat mFormatMonth = new SimpleDateFormat("MM/dd", Locale.ENGLISH);SimpleDateFormat mFormatYear = new SimpleDateFormat("MM", Locale.ENGLISH);IndexAxisValueFormatter indexAxisValueFormatter = new IndexAxisValueFormatter() {@Overridepublic String getFormattedValue(float value) {String valueString = "";long millis = System.currentTimeMillis();switch (position) {case 0:case 1:valueString = mFormatHour.format(new Date(millis));break;case 2:valueString = getWeekOfDate(millis);break;case 3:valueString = mFormatMonth.format(new Date(millis));break;case 4:valueString = mFormatYear.format(new Date(millis));break;}return valueString;}};//根据时间戳获取星期public static String getWeekOfDate(long timestamp) {String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};Calendar cal = Calendar.getInstance();cal.setTime(new Date(timestamp));int w = cal.get(Calendar.DAY_OF_WEEK) - 1;if (w < 0)w = 0;return weekDays[w];}//设置数据public void setCharDataList(LineChart chart, ArrayList<Entry> entryList, List<Float> valueList, float allValue, String unit) {//平均值float average = allValue / 10;LimitLine limitLine = new LimitLine(average, average + unit + " 平均");limitLine.enableDashedLine(10f, 10f, 0f);if (Collections.max(valueList) - average > 0.3) {limitLine.setLabelPosition(LimitLine.LimitLabelPosition.LEFT_TOP);} else {limitLine.setLabelPosition(LimitLine.LimitLabelPosition.LEFT_BOTTOM);}limitLine.setTextSize(10f);limitLine.setLineColor(Color.parseColor("#6b9cdf"));limitLine.setLineWidth(0.5f);limitLine.setTextSize(10);limitLine.setTextColor(Color.parseColor("#6b9cdf"));limitLine.setYOffset(10);//Y轴左右平均值数据YAxis leftAxis = chart.getAxisLeft();YAxis rightAxis = chart.getAxisRight();leftAxis.removeAllLimitLines();rightAxis.removeAllLimitLines();leftAxis.setDrawLimitLinesBehindData(true);rightAxis.setDrawLimitLinesBehindData(true);//Y轴左右添加平均线leftAxis.addLimitLine(limitLine);rightAxis.addLimitLine(limitLine);//填充数据LineDataSet set1 = new LineDataSet(entryList, "DataSet 1");set1.setAxisDependency(YAxis.AxisDependency.LEFT);set1.setColor(ColorTemplate.getHoloBlue());set1.setValueTextColor(ColorTemplate.getHoloBlue());set1.setLineWidth(1f);set1.setDrawCircles(false);set1.setDrawValues(false);set1.setFillAlpha(65);set1.setFillColor(Color.parseColor("#6b9cdf"));set1.setHighLightColor(Color.parseColor("#6b9cdf"));set1.setDrawCircleHole(false);//使用数据集创建数据对象LineData data = new LineData(set1);data.setValueTextColor(Color.WHITE);data.setValueTextSize(9f);//这是折线数据chart.setData(data);//动画//chart.animateX(1000);//chart.animateY(1000);//更新图表UIchart.invalidate();}//点击事件private void onViewClick(){setData(0);}//设置温度,湿度,华氏度图表数据public void setData(int tabSelectPosition) {//温度℃ArrayList<Entry> valuesTemperature = new ArrayList<>();//温度图表数据float allValueTemperature = 0;//温度平均值List<Float> temperatureList = new ArrayList<>();//温度集合//温度FArrayList<Entry> valuesTemperatureFF = new ArrayList<>();//温度图表数据float allValueTemperatureFF = 0;//温度平均值List<Float> temperatureListFF = new ArrayList<>();//温度集合//湿度ArrayList<Entry> valuesHumidity = new ArrayList<>();//湿度图表数据float allValueHumidity = 0;//湿度平均值List<Float> humidityList = new ArrayList<>();//湿度集合//温度合集List<String> list = new ArrayList<>();list.add("50");list.add("20");list.add("40");list.add("60");list.add("40");list.add("30");for (int i = 0; i < list.size(); i++) {String temperature = list.get(i);String humidity = String.valueOf(Math.random());//温度℃temperatureList.add(Float.valueOf(temperature));allValueTemperature += Float.parseFloat(temperature);valuesTemperature.add(new Entry(i, Float.parseFloat(temperature)));//温度℉temperatureListFF.add(Float.valueOf(temperature) * 1.8f + 32);allValueTemperatureFF += Float.parseFloat(temperature) * 1.8f + 32;valuesTemperatureFF.add(new Entry(i, Float.parseFloat(temperature) * 1.8f + 32));//湿度humidityList.add(Float.valueOf(humidity));allValueHumidity += Float.parseFloat(humidity);valuesHumidity.add(new Entry(i, Float.parseFloat(humidity)));}int positon = 0;switch (positon) {case 0:setCharDataList(new LineChart(context), valuesTemperatureFF, temperatureListFF, allValueTemperatureFF, "℉");break;case 1:setCharDataList(new LineChart(context), valuesTemperature, temperatureList, allValueTemperature, "℃");break;case 2:setCharDataList(new LineChart(context), valuesHumidity, humidityList, allValueHumidity, "%");break;}}
}
七 圆环进度图表,带圆角和不带圆角
7.1 带圆角效果图
7.2 自定义圆环类,有圆角,上面第一个图的样式
public class CircleProgressView extends View {private Paint mBackPaint, mProgPaint; // 绘制画笔private RectF mRectF; // 绘制区域private int[] mColorArray; // 圆环渐变色private int mProgress; // 圆环进度(0-100)public CircleProgressView(Context context) {this(context, null);}public CircleProgressView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircularProgressView);// 初始化背景圆环画笔mBackPaint = new Paint();mBackPaint.setStyle(Paint.Style.STROKE); // 只描边,不填充mBackPaint.setStrokeCap(Paint.Cap.ROUND); // 设置圆角mBackPaint.setAntiAlias(true); // 设置抗锯齿mBackPaint.setDither(true); // 设置抖动mBackPaint.setStrokeWidth(typedArray.getDimension(R.styleable.CircularProgressView_backWidth, 5));mBackPaint.setColor(typedArray.getColor(R.styleable.CircularProgressView_backColor, Color.LTGRAY));// 初始化进度圆环画笔mProgPaint = new Paint();mProgPaint.setStyle(Paint.Style.STROKE); // 只描边,不填充mProgPaint.setStrokeCap(Paint.Cap.ROUND); // 设置圆角mProgPaint.setAntiAlias(true); // 设置抗锯齿mProgPaint.setDither(true); // 设置抖动mProgPaint.setStrokeWidth(typedArray.getDimension(R.styleable.CircularProgressView_progWidth, 10));mProgPaint.setColor(typedArray.getColor(R.styleable.CircularProgressView_progColor, Color.BLUE));// 初始化进度圆环渐变色int startColor = typedArray.getColor(R.styleable.CircularProgressView_progStartColor, -1);int firstColor = typedArray.getColor(R.styleable.CircularProgressView_progFirstColor, -1);if (startColor != -1 && firstColor != -1) mColorArray = new int[]{startColor, firstColor};else mColorArray = null;// 初始化进度mProgress = typedArray.getInteger(R.styleable.CircularProgressView_progress, 0);typedArray.recycle();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int viewWide = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();int viewHigh = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();int mRectLength = (int) ((viewWide > viewHigh ? viewHigh : viewWide) - (mBackPaint.getStrokeWidth() > mProgPaint.getStrokeWidth() ? mBackPaint.getStrokeWidth() : mProgPaint.getStrokeWidth()));int mRectL = getPaddingLeft() + (viewWide - mRectLength) / 2;int mRectT = getPaddingTop() + (viewHigh - mRectLength) / 2;mRectF = new RectF(mRectL, mRectT, mRectL + mRectLength, mRectT + mRectLength);// 设置进度圆环渐变色if (mColorArray != null && mColorArray.length > 1)mProgPaint.setShader(new LinearGradient(0, 0, 0, getMeasuredWidth(), mColorArray, null, Shader.TileMode.MIRROR));}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawArc(mRectF, 0, 360, false, mBackPaint);canvas.drawArc(mRectF, 275, 360 * mProgress / 100, false, mProgPaint);}// ---------------------------------------------------------------------------------------------/*** 获取当前进度** @return 当前进度(0-100)*/public int getProgress() {return mProgress;}/*** 设置当前进度** @param progress 当前进度(0-100)*/public void setProgress(int progress) {this.mProgress = progress;invalidate();}/*** 设置当前进度,并展示进度动画。如果动画时间小于等于0,则不展示动画** @param progress 当前进度(0-100)* @param animTime 动画时间(毫秒)*/public void setProgress(int progress, long animTime) {if (animTime <= 0) setProgress(progress);else {ValueAnimator animator = ValueAnimator.ofInt(mProgress, progress);animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {mProgress = (int) animation.getAnimatedValue();invalidate();}});animator.setInterpolator(new OvershootInterpolator());animator.setDuration(animTime);animator.start();}}/*** 设置背景圆环宽度** @param width 背景圆环宽度*/public void setBackWidth(int width) {mBackPaint.setStrokeWidth(width);invalidate();}/*** 设置背景圆环颜色** @param color 背景圆环颜色*/public void setBackColor(@ColorRes int color) {mBackPaint.setColor(ContextCompat.getColor(getContext(), color));invalidate();}/*** 设置进度圆环宽度** @param width 进度圆环宽度*/public void setProgWidth(int width) {mProgPaint.setStrokeWidth(width);invalidate();}/*** 设置进度圆环颜色** @param color 景圆环颜色*/public void setProgColor(@ColorRes int color) {mProgPaint.setColor(ContextCompat.getColor(getContext(), color));mProgPaint.setShader(null);invalidate();}/*** 设置进度圆环颜色(支持渐变色)** @param startColor 进度圆环开始颜色* @param firstColor 进度圆环结束颜色*/public void setProgColor(@ColorRes int startColor, @ColorRes int firstColor) {mColorArray = new int[]{ContextCompat.getColor(getContext(), startColor), ContextCompat.getColor(getContext(), firstColor)};mProgPaint.setShader(new LinearGradient(0, 0, 0, getMeasuredWidth(), mColorArray, null, Shader.TileMode.MIRROR));invalidate();}/*** 设置进度圆环颜色(支持渐变色)** @param colorArray 渐变色集合*/public void setProgColor(@ColorRes int[] colorArray) {if (colorArray == null || colorArray.length < 2) return;mColorArray = new int[colorArray.length];for (int index = 0; index < colorArray.length; index++)mColorArray[index] = ContextCompat.getColor(getContext(), colorArray[index]);mProgPaint.setShader(new LinearGradient(0, 0, 0, getMeasuredWidth(), mColorArray, null, Shader.TileMode.MIRROR));invalidate();}
}
使用:
xml添加控件
<RelativeLayoutandroid:layout_width="177dp"android:layout_height="177dp"android:layout_gravity="center_horizontal"android:layout_marginTop="25dp"android:gravity="center_horizontal"><FrameLayoutandroid:layout_width="177dp"android:layout_height="177dp"><Viewandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_margin="4dp"android:background="@drawable/shape_bg_f2efff"/><com.example.finance.CircleProgressViewandroid:id="@+id/cp_progress"android:layout_width="match_parent"android:layout_height="match_parent"app:backColor="@color/trans"app:backWidth="8dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:progColor="@color/color_blue"app:progWidth="8dp"app:progress="0" /></FrameLayout><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:gravity="center"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="24dp"android:text="BMI"android:textColor="#ff262729"android:textSize="20sp" /><TextViewandroid:id="@+id/tv_progress"android:layout_width="wrap_content"android:layout_height="24dp"android:text="0"android:textStyle="bold"android:textColor="#ff7783ff"android:textSize="20sp" /><TextViewandroid:id="@+id/tv_progress_value"android:layout_width="wrap_content"android:layout_height="16dp"android:text="你的体型很标准哦"android:textColor="#ff262729"android:layout_marginTop="13dp"android:textSize="12sp" /></LinearLayout></RelativeLayout>
java设置圆环进度:
CircleProgressView cpProgress = (CircleProgressView) findViewById(R.id.cp_progress);
cpProgress.setProgress((int) (30/60f*100));
7.3 不带圆角效果图
7.4 xml添加组件
<androidx.cardview.widget.CardViewandroid:id="@+id/cl_budget"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginLeft="15dp"android:layout_marginTop="20dp"android:layout_marginRight="15dp"app:cardBackgroundColor="@color/white"app:cardCornerRadius="@dimen/dp_5"app:cardElevation="3dp"><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_width="110dp"android:layout_height="110dp"android:layout_gravity="center_vertical"android:layout_marginLeft="20dp"android:layout_marginTop="25dp"android:layout_marginBottom="25dp"><com.dinghe.financeapp.utils.CircleProgressViewandroid:id="@+id/cp_progress"android:layout_width="0dp"android:layout_height="0dp"app:backColor="@color/color_d8d8d8"app:backWidth="8dp"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"app:progColor="@color/color_blue"app:progWidth="8dp"app:progress="0" /><TextViewandroid:id="@+id/tv_progress"style="@style/Font_black"android:layout_centerInParent="true"android:text="0"android:textColor="@color/color_3d"android:textSize="24sp"android:textStyle="bold"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><TextViewstyle="@style/Font_black"android:layout_marginLeft="4dp"android:layout_marginBottom="3dp"android:text="%"android:textColor="@color/color_3d"android:textSize="14sp"app:layout_constraintBottom_toBottomOf="@id/tv_progress"app:layout_constraintLeft_toRightOf="@id/tv_progress" /></androidx.constraintlayout.widget.ConstraintLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:layout_marginLeft="140dp"android:layout_marginRight="15dp"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_vertical"><TextViewstyle="@style/Font_black"android:layout_centerVertical="true"android:text="@string/me_budget"android:textSize="17sp"android:textStyle="bold" /><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:src="@mipmap/ic_next2" /></RelativeLayout><TextViewandroid:id="@+id/tv_budget_amount"style="@style/Font_black"android:layout_marginTop="10dp"android:text="@string/me_budget_amount"android:textSize="14sp" /><TextViewandroid:id="@+id/tv_budget_outlay"style="@style/Font_black"android:layout_marginTop="5dp"android:text="@string/me_budget_outlay"android:textSize="14sp" /><TextViewandroid:id="@+id/tv_budget_balance"style="@style/Font_black"android:layout_marginTop="5dp"android:text="@string/me_budget_balance"android:textSize="14sp" /></LinearLayout>
</androidx.cardview.widget.CardView>
java设置进度
CircleProgressView cpProgress = (CircleProgressView) findViewById(R.id.cp_progress);
cpProgress.setProgress((int) (30/80f*100));
八 仪表图
8.1 效果图
8.2 自定义仪表盘View
public class DashboardView3 extends BaseDashboardView {//外环画笔private Paint mPaintOuterArc;//内环画笔private Paint mPaintInnerArc;//进度点画笔private Paint mPaintProgressPoint;//指示器画笔private Paint mPaintIndicator;//外环区域private RectF mRectOuterArc;//内环区域private RectF mRectInnerArc;//圆环画笔颜色private int mOuterArcColor;private int mProgressOuterArcColor;//内环画笔颜色private int mInnerArcColor;private int mProgressInnerArcColor;//内外环之间的间距private float mArcSpacing;//进度条的圆点属性private float[] mProgressPointPosition;private float mProgressPointRadius;//指标器的Pathprivate Path mIndicatorPath;//指示器的起始位置private float mIndicatorStart;//默认圆环之间间距private static final float DEFAULT_ARC_SPACING = 10;//外环的默认属性private static final float DEFAULT_OUTER_ARC_WIDTH = 1.5f;private static final int DEFAULT_OUTER_ARC_COLOR = Color.argb(80, 255, 255, 255);//外环进度的默认属性private static final int DEFAULT_PROGRESS_OUTER_ARC_COLOR = Color.argb(200, 255, 255, 255);//进度点的默认属性private static final float DEFAULT_PROGRESS_POINT_RADIUS = 3;private static final int DEFAULT_PROGRESS_POINT_COLOR = Color.WHITE;//内环默认属性private static final float DEFAULT_INNER_ARC_WIDTH = 1.5f;private static final int DEFAULT_INNER_ARC_COLOR = Color.argb(50, 255, 255, 255);//内环进度的默认属性private static final int DEFAULT_PROGRESS_INNER_ARC_COLOR = Color.argb(170, 255, 255, 255);//指示器默认属性private static final int DEFAULT_INDICATOR_COLOR = Color.argb(200, 255, 255, 255);public DashboardView3(Context context) {this(context, null);}public DashboardView3(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public DashboardView3(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}/*** 初始化界面*/@Overrideprotected void initView() {//默认数据mArcSpacing = dp2px(DEFAULT_ARC_SPACING);mOuterArcColor = DEFAULT_OUTER_ARC_COLOR;mProgressOuterArcColor = DEFAULT_PROGRESS_OUTER_ARC_COLOR;mProgressPointRadius = dp2px(DEFAULT_PROGRESS_POINT_RADIUS);mInnerArcColor = DEFAULT_INNER_ARC_COLOR;mProgressInnerArcColor = DEFAULT_PROGRESS_INNER_ARC_COLOR;//初始化画笔//外环画笔mPaintOuterArc = new Paint(Paint.ANTI_ALIAS_FLAG);mPaintOuterArc.setStrokeWidth(dp2px(DEFAULT_OUTER_ARC_WIDTH));mPaintOuterArc.setStyle(Paint.Style.STROKE);//内环画笔mPaintInnerArc = new Paint(Paint.ANTI_ALIAS_FLAG);mPaintInnerArc.setStrokeWidth(dp2px(DEFAULT_INNER_ARC_WIDTH));mPaintInnerArc.setStyle(Paint.Style.STROKE);mPaintInnerArc.setStrokeCap(Paint.Cap.ROUND);PathEffect mPathEffect = new DashPathEffect(new float[] { 10, 10 }, 0);mPaintInnerArc.setPathEffect(mPathEffect);//进度点画笔mPaintProgressPoint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaintProgressPoint.setStyle(Paint.Style.FILL);mPaintProgressPoint.setColor(DEFAULT_PROGRESS_POINT_COLOR);//指示器画笔mPaintIndicator = new Paint(Paint.ANTI_ALIAS_FLAG);mPaintIndicator.setStrokeCap(Paint.Cap.SQUARE);mPaintIndicator.setColor(DEFAULT_INDICATOR_COLOR);mPaintIndicator.setStrokeWidth(dp2px(1));//进度点的图片mProgressPointPosition = new float[2];}/*** 初始化圆环区域*/@Overrideprotected void initArcRect(float left, float top, float right, float bottom) {//外环区域mRectOuterArc = new RectF(left, top, right, bottom);initInnerRect();}/*** 初始化内部的区域*/private void initInnerRect() {//内环位置mRectInnerArc = new RectF(mRectOuterArc.left + mArcSpacing,mRectOuterArc.top + mArcSpacing,mRectOuterArc.right - mArcSpacing , mRectOuterArc.bottom - mArcSpacing);//指标器的路径mIndicatorStart = mRectInnerArc.top + mArcSpacing / 2;mIndicatorPath = new Path();mIndicatorPath.moveTo(mRadius, mIndicatorStart);mIndicatorPath.rLineTo(-dp2px(2), dp2px(5));mIndicatorPath.rLineTo(dp2px(4), 0);mIndicatorPath.close();}/*** 绘制圆环*/@Overrideprotected void drawArc(Canvas canvas, float arcStartAngle, float arcSweepAngle) {//绘制圆环mPaintOuterArc.setColor(mOuterArcColor);canvas.drawArc(mRectOuterArc, arcStartAngle, arcSweepAngle, false, mPaintOuterArc);//绘制内环mPaintInnerArc.setColor(mInnerArcColor);canvas.drawArc(mRectInnerArc, arcStartAngle, arcSweepAngle, false, mPaintInnerArc);}/*** 绘制进度圆环*/@Overrideprotected void drawProgressArc(Canvas canvas, float arcStartAngle, float progressSweepAngle) {//绘制进度点if(progressSweepAngle == 0) {return;}Path path = new Path();//添加进度圆环的区域path.addArc(mRectOuterArc, arcStartAngle, progressSweepAngle);//计算切线值和为重PathMeasure pathMeasure = new PathMeasure(path, false);pathMeasure.getPosTan(pathMeasure.getLength(), mProgressPointPosition, null);//绘制圆环mPaintOuterArc.setColor(mProgressOuterArcColor);canvas.drawPath(path, mPaintOuterArc);//绘制进度点if(mProgressPointPosition[0] != 0 && mProgressPointPosition[1] != 0) {canvas.drawCircle(mProgressPointPosition[0], mProgressPointPosition[1], mProgressPointRadius, mPaintProgressPoint);}//绘制内环mPaintInnerArc.setColor(mProgressInnerArcColor);canvas.drawArc(mRectInnerArc, arcStartAngle, progressSweepAngle, false, mPaintInnerArc);//绘制指针canvas.save();canvas.rotate(arcStartAngle + progressSweepAngle - 270, mRadius, mRadius);mPaintIndicator.setStyle(Paint.Style.FILL);canvas.drawPath(mIndicatorPath, mPaintIndicator);mPaintIndicator.setStyle(Paint.Style.STROKE);canvas.drawCircle(mRadius, mIndicatorStart + dp2px(6) + 1, dp2px(2), mPaintIndicator);canvas.restore();}/*** 绘制文字*/@Overrideprotected void drawText(Canvas canvas, int value, String valueLevel, String currentTime) {//绘制数值float marginTop = mRadius + mTextSpacing;canvas.drawText(String.valueOf(value), mRadius, marginTop, mPaintValue);//绘制数值文字信息if(!TextUtils.isEmpty(valueLevel)){float margin = mRadius - mTextSpacing - getPaintHeight(mPaintValue, "9");canvas.drawText(valueLevel, mRadius, margin, mPaintValueLevel);}//绘制日期if(!TextUtils.isEmpty(currentTime)) {marginTop = marginTop + getPaintHeight(mPaintDate, currentTime) + mTextSpacing;canvas.drawText(currentTime, mRadius, marginTop, mPaintDate);}}/*** 设置圆环的距离*/public void setArcSpacing(float dpSize){mArcSpacing = dp2px(dpSize);initInnerRect();postInvalidate();}/*** 设置外环颜色*/public void setOuterArcPaint(float dpSize, @ColorInt int color){mPaintOuterArc.setStrokeWidth(dp2px(dpSize));mOuterArcColor = color;postInvalidate();}/*** 设置进度条的颜色*/public void setProgressOuterArcColor(@ColorInt int color){mProgressOuterArcColor = color;postInvalidate();}/*** 设置内环的属性*/public void setInnerArcPaint(float dpSize, @ColorInt int color){mPaintInnerArc.setStrokeWidth(dp2px(dpSize));mInnerArcColor = color;postInvalidate();}/*** 设置内环的属性*/public void setProgressInnerArcPaint(@ColorInt int color){mProgressInnerArcColor = color;postInvalidate();}/*** 设置内环实线和虚线状态*/public void setInnerArcPathEffect(float[] intervals){PathEffect mPathEffect = new DashPathEffect(intervals, 0);mPaintInnerArc.setPathEffect(mPathEffect);postInvalidate();}/*** 设置进度圆点的属性*/public void setProgressPointPaint(float dpRadiusSize,@ColorInt int color){mProgressPointRadius = dp2px(dpRadiusSize);mPaintProgressPoint.setColor(color);postInvalidate();}/*** 设置指示器属性*/public void setIndicatorPaint(@ColorInt int color){mPaintIndicator.setColor(color);postInvalidate();}
}
8.3 使用:
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@drawable/bg"android:gravity="center_horizontal"><com.github.iron.chart.dashboard.DashboardView3android:id="@+id/dv"android:layout_width="250dp"android:layout_height="180dp"android:layout_marginTop="30dp"android:layout_marginBottom="40dp" />
</LinearLayout>
DashboardView3 dashboardView= findViewById(R.id.dv);
dashboardView.setDateStrPattern("评估时间:2023-05-25");
dashboardView.setValueLevelPattern("信用优秀");
int max = dashboardView.getMax();
int min = dashboardView.getMin();
dashboardView.setValue(new Random().nextInt(max - min) + min, anim, reset);