一 简介
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.BarChart
android:id="@+id/chart1"
android:layout_width="match_parent"
android:layout_height="300dp" />
</FrameLayout>
2.5 设置图表配置和数据
public class BarActivity extends AppCompatActivity {
private BarChart chart;
@Override
protected 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);
// 刷新图表UI
chart.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.PieChart
android:id="@+id/chart1"
android:layout_width="match_parent"
android:layout_height="300dp" />
</LinearLayout>
3.3 Activity里面配置参数和数据
public class PieCharActivity extends Activity {
private PieChart chart;
@Override
protected 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() {
@Override
public void onValueSelected(Entry e, Highlight h) {
//选中的扇页
}
@Override
public 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);
//刷新图表UI
chart.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.PieChart
android: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;
@Override
protected 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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<View
android:id="@+id/view_statues"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@color/white" />
<RelativeLayout
android:id="@+id/v_title_layout"
android:layout_width="match_parent"
android:layout_height="44dp"
android:background="@color/white">
<ImageView
android: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" />
<LinearLayout
android: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">
<TextView
android: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" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/down_white" />
</LinearLayout>
</RelativeLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android: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" />
<TextView
android: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" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="18dp"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/v_pie_chart"
android:layout_width="match_parent"
android:layout_height="228dp" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<TextView
android: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" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<TextView
android: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" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<TextView
android: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>
<TextView
android: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" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<TextView
android: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" />
<TextView
android: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>
<FrameLayout
android: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.LineChart
android: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;
@Override
protected 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() {
@Override
public 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;
@Override
protected int getLayoutId() {
return R.layout.activity_statistics;
}
@Override
public void initData() {
hideTitleLayout(mDataBinding.viewStatues);
mDataBinding.vBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
mDataBinding.vDate.setOnClickListener(new View.OnClickListener() {
@Override
public 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.setExtraOffsets(20, 0.f, 20, 0.f);
pieChart.setDrawHoleEnabled(true);
pieChart.setHoleColor(Color.TRANSPARENT);
pieChart.setTransparentCircleColor(Color.WHITE);
pieChart.setTransparentCircleAlpha(110);
pieChart.setHoleRadius(58f);
pieChart.setDrawHoleEnabled(false);
pieChart.setTransparentCircleRadius(61f);
pieChart.setDrawCenterText(true);
pieChart.setRotationAngle(90);
// enable rotation of the chart by touch
pieChart.setRotationEnabled(true);
pieChart.setHighlightPerTapEnabled(true);
// chart.setUnit(" €");
// chart.setDrawUnitsInChart(true);
// add a selection listener
// 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);
// add a lot of colors
ArrayList<Integer> colors = new ArrayList<>();
colors.add(Color.parseColor("#37F0A2"));
colors.add(Color.parseColor("#49DBEE"));
colors.add(Color.parseColor("#43C088"));
dataSet.setColors(colors);
//dataSet.setSelectionShift(0f);
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);
// undo all highlights
pieChart.highlightValues(null);
pieChart.invalidate();
}
private void initLineChar() {
//chart.setOnChartValueSelectedListener(this);
// no description text
chart.getDescription().setEnabled(false);
chart.setDescription(null);
// enable touch gestures
chart.setTouchEnabled(true);
chart.setDragDecelerationFrictionCoef(0.9f);
// enable scaling and dragging
chart.setDragEnabled(false);
chart.setScaleEnabled(false);
chart.setDrawGridBackground(false);
chart.setHighlightPerDragEnabled(true);
// if disabled, scaling can be done on x- and y-axis separately
chart.setPinchZoom(true);
// set an alternative background color
chart.setBackgroundColor(Color.TRANSPARENT);
chart.animateX(700);
chart.setNoDataText("暫無數據");
//间距
//chart.setViewPortOffsets(StatuesBarUtils.dp2px(mContext,10), 0, 0, StatuesBarUtils.dp2px(mContext,10));
XAxis xAxis = chart.getXAxis();
//xAxis.setTypeface(tfLight);
xAxis.setTextSize(11f);
xAxis.setTextColor(Color.parseColor("#999999"));
xAxis.setDrawGridLines(false);
xAxis.setDrawAxisLine(false);
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setAxisLineColor(Color.parseColor("#ECECEC"));
xAxis.setGridColor(Color.parseColor("#ECECEC"));
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"));
YAxis rightAxis = chart.getAxisRight();
rightAxis.setEnabled(false);
//图例
Legend legend = chart.getLegend();
legend.setEnabled(false);
setLineData(5);
}
private List<Entry> allEntryList = new ArrayList<>();
private void setLineData(int month) {
ArrayList<Entry> values1 = new ArrayList<>();
if (month >= 5) {
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));
if (month >= 6) {
values1.add(new Entry(5, 40f));
}
}
ArrayList<Entry> values2 = new ArrayList<>();
if (month >= 5) {
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));
if (month >= 6) {
values2.add(new Entry(5, 30f));
}
}
updateData(values1, values2);
}
private void updateData(ArrayList<Entry> values1, ArrayList<Entry> values2) {
List<LineDataSet> lineDataSetList = new ArrayList<>();
if (values1.size() > 0) {
LineDataSet set1 = new LineDataSet(values1, null);
// create a dataset and give it a type
set1.setAxisDependency(YAxis.AxisDependency.LEFT);
set1.setColor(Color.parseColor("#35E5FF"));
set1.setCircleColor(Color.parseColor("#FFBD02"));
set1.setLineWidth(2f);
set1.setCircleRadius(3f);
set1.setFillAlpha(80);
set1.setHighLightColor(Color.TRANSPARENT);
set1.setDrawCircleHole(false);
set1.setDrawFilled(true);
//set1.setFillFormatter(new MyFillFormatter(0f));
set1.setDrawHorizontalHighlightIndicator(false);
//set1.setVisible(false);
set1.setCircleHoleColor(Color.TRANSPARENT);
if (Utils.getSDKInt() >= 18) {
// drawables only supported on api level 18 and above
Drawable 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) {
// drawables only supported on api level 18 and above
Drawable 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()]);
// create a data object with the data sets
LineData data = new LineData(lineDataSets);
data.setValueTextColor(Color.TRANSPARENT);
data.setValueTextSize(9f);
// set data
chart.setData(data);
//设置x轴值
chart.getXAxis().setLabelCount(values1.size(), true);
chart.getXAxis().setValueFormatter(new ValueFormatter() {
@Override
public 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) {
chart.getAxisLeft().setAxisMaximum(Collections.max(floatYList) + 10);
chart.getAxisLeft().setValueFormatter(new ValueFormatter() {
@Override
public String getFormattedValue(float v) {
return String.valueOf(v);
}
});
}
} else {
chart.setData(null);
}
chart.invalidate();
}
//
private TimePickerView agePickView;//年龄选择器
public void initDatePicker() {
Calendar startca = Calendar.getInstance();
startca.set(startca.get(Calendar.YEAR) - 70, 0, 0);
Calendar nowca = Calendar.getInstance();
Calendar endca = Calendar.getInstance();
endca.add(Calendar.MONTH, 1);
if (agePickView == null) {
agePickView = new TimePickerBuilder(mContext, new OnTimeSelectListener() {
@Override
public void onTimeSelect(Date date, View v) {
agePickView.dismiss();
String time = convertTimestampDate(date.getTime());
mDataBinding.tvDate.setText(time);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int checkMonth = calendar.get(Calendar.MONTH) + 1;
setLineData(checkMonth);
}
})
.setTitleText("日期")
.setDate(nowca)
.setRangDate(startca, endca)
.setType(new boolean[]{true, true, false, false, false, false})
.setLabel("年", "月", null, null, null, null)
.setContentTextSize(16)
.setSubCalSize(16)
.setDividerColor(getResources().getColor(R.color.color_eeeeee))
.setTextColorCenter(getResources().getColor(R.color.black)) //设置选中项文字颜色
.setTextColorOut(getResources().getColor(R.color.color_text_999))//设置未选中项文字颜色
.setSubmitColor(getResources().getColor(R.color.them))
.setCancelColor(getResources().getColor(R.color.color_text_title))
.setTitleBgColor(getResources().getColor(R.color.white))
.setLineSpacingMultiplier(2.5f)
.isDialog(true) //默认设置false ,内部实现将DecorView 作为它的父控件。
.build();
Dialog mDialog = agePickView.getDialog();
if (mDialog != null) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
Gravity.BOTTOM);
params.leftMargin = 0;
params.rightMargin = 0;
agePickView.getDialogContainerLayout().setLayoutParams(params);
Window dialogWindow = mDialog.getWindow();
if (dialogWindow != null) {
dialogWindow.setWindowAnimations(com.bigkoo.pickerview.R.style.picker_view_slide_anim);//修改动画样式
dialogWindow.setGravity(Gravity.BOTTOM);//改成Bottom,底部显示
}
}
}
if (mContext != null && !isFinishing()) {
agePickView.show();
}
}
public String convertTimestampDate(Long timestamp) {
Date date = new Date(timestamp);
SimpleDateFormat format = new SimpleDateFormat("yyyy.MM");
return format.format(date);
}
}
六 折线图进阶,添加平均值限制线
6.1 效果图
6.2 直接上配置吧
public class LineChartViewUtils {
private Context context;
private View view;
private LinearLayout llRootLayout;
private TempChartViewUtils tempChartViewUtils;
private HumidityChartViewUtils humidityChartViewUtils;
private DewpointChartViewUtils dewpointChartViewUtils;
private VpdChartViewUtils vpdChartViewUtils;
private List<Long> reportTimeList = new ArrayList<>();
private int tabSelectPosition;
private List<ThermobHistoryResponse.DataDTO.ListDTO> list=new ArrayList<>();
public LineChartViewUtils(Context context) {
this.context = context;
view = LayoutInflater.from(context).inflate(R.layout.layout_line_char_utils, null);
initView();
initData();
}
public View getView() {
return view;
}
private void initView() {
llRootLayout = (LinearLayout) view.findViewById(R.id.ll_root_layout);
}
private void initData() {
addDataChartView();
}
private void addDataChartView() {
llRootLayout.removeAllViews();
tempChartViewUtils = new TempChartViewUtils(context);
llRootLayout.addView(tempChartViewUtils.getView());
humidityChartViewUtils = new HumidityChartViewUtils(context);
llRootLayout.addView(humidityChartViewUtils.getView());
// dewpointChartViewUtils = new DewpointChartViewUtils(context);
// llRootLayout.addView(dewpointChartViewUtils.getView());
//
// vpdChartViewUtils = new VpdChartViewUtils(context);
// llRootLayout.addView(vpdChartViewUtils.getView());
if (tempChartViewUtils != null) {
initChart(tempChartViewUtils.getChart());
tempChartViewUtils.getRgGroup().setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
DeviceActivity.tempSymbol=tempChartViewUtils.getRb1().isChecked()?"1":"0";
setData(tabSelectPosition,list);
}
});
}
if (humidityChartViewUtils != null) {
initChart(humidityChartViewUtils.getChart());
}
if (dewpointChartViewUtils != null) {
initChart(dewpointChartViewUtils.getChart());
}
if (vpdChartViewUtils != null) {
initChart(vpdChartViewUtils.getChart());
}
}
private void initChart(LineChart chart) {
chart.getDescription().setEnabled(false);
//
// // enable touch gestures
// chart.setTouchEnabled(true);
//
// chart.setDragDecelerationFrictionCoef(0.9f);
//
// // enable scaling and dragging
// chart.setDragEnabled(true);
// chart.setScaleEnabled(true);
chart.setHighlightPerDragEnabled(false);
// chart.setBorderColor(context.getColor(R.color.color_gray_dadada));
// chart.setDrawBorders(true);
//
// // set an alternative background color
// chart.setBackgroundColor(Color.WHITE);
// chart.setViewPortOffsets(0f, 0f, 0f, 0f);
// get the legend (only possible after setting data)
Legend l = chart.getLegend();
l.setEnabled(false);
//
XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTH_SIDED);
xAxis.setTypeface(tfLight);
xAxis.setTextSize(10f);
xAxis.setTextColor(context.getColor(R.color.color_999999));
xAxis.setDrawAxisLine(true);
xAxis.setAxisLineColor(context.getColor(R.color.color_gray_dadada));
xAxis.setAxisLineWidth(0.5f);
xAxis.setDrawGridLines(true);
xAxis.setGridColor(context.getColor(R.color.color_gray_dadada));
xAxis.setGridLineWidth(0.5f);
// xAxis.setCenterAxisLabels(false);
// xAxis.setGranularity(1f); // one hour
chart.getXAxis().setValueFormatter(indexAxisValueFormatter);
YAxis leftAxis = chart.getAxisLeft();
leftAxis.setEnabled(true);
leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
leftAxis.setTextColor(Color.TRANSPARENT);
leftAxis.setDrawGridLines(false);
leftAxis.setDrawAxisLine(false);
// leftAxis.setTypeface(tfLight);
// leftAxis.setGranularityEnabled(true);
// leftAxis.setAxisMinimum(0f);
// leftAxis.setAxisMaximum(170f);
leftAxis.setYOffset(-9f);
YAxis rightAxis = chart.getAxisRight();
rightAxis.setEnabled(true);
rightAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
rightAxis.setTextColor(Color.TRANSPARENT);
rightAxis.setDrawGridLines(false);
rightAxis.setDrawAxisLine(false);
}
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() {
@Override
public String getFormattedValue(float value) {
String valueString = "";
if ((int) value < reportTimeList.size()) {
long millis = reportTimeList.get((int) value);
switch (tabSelectPosition) {
case 0:
case 1:
valueString = mFormatHour.format(new Date(millis));
break;
case 2:
valueString = DateTimeUtil.getWeekOfDate(millis);
break;
case 3:
valueString = mFormatMonth.format(new Date(millis));
break;
case 4:
valueString = mFormatYear.format(new Date(millis));
break;
}
}
return valueString;
}
};
//设置数据
public void setCharDataList(LineChart chart, ArrayList<Entry> entryList, List<Float> valueList, float allValue, String unit) {
/**
* 平均值
*/
float average = allValue / valueList.size();
LimitLine llXAxis = new LimitLine(average, ByteUtils.decimalFloatDouble(average) + unit + " 平均");
llXAxis.enableDashedLine(10f, 10f, 0f);
if(Collections.max(valueList)-average>0.3){
llXAxis.setLabelPosition(LimitLine.LimitLabelPosition.LEFT_TOP);
}else {
llXAxis.setLabelPosition(LimitLine.LimitLabelPosition.LEFT_BOTTOM);
}
llXAxis.setTextSize(10f);
llXAxis.setLineColor(context.getColor(R.color.color_6b9cdf));
llXAxis.setLineWidth(0.5f);
llXAxis.setTextSize(10);
llXAxis.setTextColor(context.getColor(R.color.color_999999));
llXAxis.setYOffset(10);
YAxis leftAxis = chart.getAxisLeft();
YAxis rightAxis = chart.getAxisRight();
leftAxis.removeAllLimitLines();
rightAxis.removeAllLimitLines();
leftAxis.setDrawLimitLinesBehindData(true);
rightAxis.setDrawLimitLinesBehindData(true);
leftAxis.addLimitLine(llXAxis);
rightAxis.addLimitLine(llXAxis);
/**
* 填充数据
*/
// create a dataset and give it a type
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(context.getColor(R.color.color_6b9cdf));
set1.setHighLightColor(context.getColor(R.color.color_6b9cdf));
set1.setDrawCircleHole(false);
// create a data object with the data sets
LineData data = new LineData(set1);
data.setValueTextColor(Color.WHITE);
data.setValueTextSize(9f);
// set data
chart.setData(data);
// chart.animateX(1000);
// chart.animateY(1000);
chart.invalidate();
}
//设置图表数据
public void setData(int tabSelectPosition, List<ThermobHistoryResponse.DataDTO.ListDTO> list) {
this.list=list;
this.tabSelectPosition = tabSelectPosition;
if (list.size() > 0) {
//温度℃
ArrayList<Entry> valuesTemperature = new ArrayList<>();//温度图表数据
float allValueTemperature = 0;//温度平均值
List<Float> temperatureList = new ArrayList<>();//温度集合
//温度F
ArrayList<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<>();//湿度集合
reportTimeList.clear();
// increment by 1 hour
for (int i = 0; i < list.size(); i++) {
ThermobHistoryResponse.DataDTO.ListDTO listDTO = list.get(i);
reportTimeList.add(listDTO.reportTime);
//温度℃
temperatureList.add(Float.valueOf(listDTO.temperature));
allValueTemperature += Float.parseFloat(listDTO.temperature);
valuesTemperature.add(new Entry(i, Float.parseFloat(listDTO.temperature)));
//温度℉
temperatureListFF.add(Float.valueOf(listDTO.temperature)*1.8f+32);
allValueTemperatureFF += Float.parseFloat(listDTO.temperature)*1.8f+32;
valuesTemperatureFF.add(new Entry(i, Float.parseFloat(listDTO.temperature)*1.8f+32));
//湿度
humidityList.add(Float.valueOf(listDTO.humidity));
allValueHumidity += Float.parseFloat(listDTO.humidity);
valuesHumidity.add(new Entry(i, Float.parseFloat(listDTO.humidity)));
}
if (tempChartViewUtils != null) {
if(tempChartViewUtils.getRb1().isChecked()){
setCharDataList(tempChartViewUtils.getChart(), valuesTemperatureFF, temperatureListFF, allValueTemperatureFF, "℉");
tempChartViewUtils.setDataListFF(temperatureListFF, reportTimeList);
}else {
setCharDataList(tempChartViewUtils.getChart(), valuesTemperature, temperatureList, allValueTemperature, "℃");
tempChartViewUtils.setDataList(temperatureList, reportTimeList);
}
}
if (humidityChartViewUtils != null) {
setCharDataList(humidityChartViewUtils.getChart(), valuesHumidity, humidityList, allValueHumidity, "%");
humidityChartViewUtils.setDataList(humidityList, reportTimeList);
}
}else {
if (tempChartViewUtils != null) {
tempChartViewUtils.getChart().clear();
tempChartViewUtils.getChart().invalidate();
}
if (humidityChartViewUtils != null) {
humidityChartViewUtils.getChart().clear();
humidityChartViewUtils.getChart().invalidate();
}
}
}
}