MPAndroidChart的画图方式
study by https://www.cnblogs.com/r-decade/p/6241693.html https://blog.csdn.net/u014136472/article/details/50298213
- LineChart
- BarChart
- ScatterChart
- CandleStickChart
- PieChart
- BubbleChart or RadarChart
刷新api
-
invalidate() : 在chart中调用会使其刷新重绘
-
notifyDataSetChanged() : 让chart知道它依赖的基础数据已经改变,并执行所有必要的重新计算(比如偏移量,legend,最大值,最小值 …)。在动态添加数据时需要用到。
基本的chart风格
<!--折线图,layout的背景色为 #bdbdbd 灰-->
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/line_chart"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#ffffff"
android:layout_margin="16dp"/>
chart 也可以使用java代码改变风格
- setBackgroundColor(int color): 设置背景颜色,将覆盖整个图表视图。
setDescription(String desc)
: 设置图表的描述文字,会显示在图表的右下角。setDescriptionColor(int color)
: 设置描述文字的颜色。setDescriptionPosition(float x, float y)
: 自定义描述文字在屏幕上的位置(单位是像素)。setDescriptionTypeface(Typeface t)
: 设置描述文字的 Typeface。setDescriptionTextSize(float size)
: 设置以像素为单位的描述文字,最小6f,最大16f。setNoDataTextDescription(String desc)
: 设置当 chart 为空时显示的描述文字。setDrawGridBackground(boolean enabled)
: 如果启用,chart 绘图区后面的背景矩形将绘制。setGridBackgroundColor(int color)
: 设置网格背景应与绘制的颜色。setDrawBorders(boolean enabled)
: 启用/禁用绘制图表边框(chart周围的线)。setBorderColor(int color)
: 设置 chart 边框线的颜色。setBorderWidth(float width)
: 设置 chart 边界线的宽度,单位 dp。setMaxVisibleValueCount(int count)
: 设置最大可见绘制的 chart count 的数量。 只在setDrawValues()
设置为true
时有效。
手势交互
-
setTouchEnabled(boolean enabled)
: 启用/禁用与图表的所有可能的触摸交互。 -
setDragEnabled(boolean enabled)
: 启用/禁用拖动(平移)图表。 -
setScaleEnabled(boolean enabled)
: 启用/禁用缩放图表上的两个轴。 -
setScaleXEnabled(boolean enabled)
: 启用/禁用缩放在x轴上。 -
setScaleYEnabled(boolean enabled)
: 启用/禁用缩放在y轴。 -
setPinchZoom(boolean enabled)
: 如果设置为true,捏缩放功能。 如果false,x轴和y轴可分别放大。 -
setDoubleTapToZoomEnabled(boolean enabled)
: 设置为false以禁止通过在其上双击缩放图表。 -
setHighlightPerDragEnabled(boolean enabled)
: 设置为true,允许每个图表表面拖过,当它完全缩小突出。 默认值:true -
setHighlightPerTapEnabled(boolean enabled)
: 设置为false,以防止值由敲击姿态被突出显示。 值仍然可以通过拖动或编程方式突出显示。 默认值:true图表的 抛掷/减速
setDragDecelerationEnabled(boolean enabled)
: 如果设置为true,手指滑动抛掷图表后继续减速滚动。 默认值:true。setDragDecelerationFrictionCoef(float coef)
: 减速的摩擦系数在[0; 1]区间,数值越高表示速度会缓慢下降,例如,如果将其设置为0,将立即停止。 1是一个无效的值,会自动转换至0.9999。
高亮
highlightValues(Highlight[] highs)
: 高亮显示值,高亮显示的点击的位置在数据集中的值。 设置null或空数组则撤消所有高亮。highlightValue(int xIndex, int dataSetIndex)
: 高亮给定xIndex在数据集的值。 设置xIndex或dataSetIndex为-1撤消所有高亮。getHighlighted()
: 返回一个Highlight[]
其中包含所有高亮对象的信息,xIndex和dataSetIndex。
坐标轴
在文档中,AxisBase是XAxis和YAxis的父类
- XAxis是x轴的标签设置,只使用setter方法修改,不要直接访问公共变量
- YAxis是y轴的标签设置,只使用setter方法修改,不要直接访问公共变量
控制轴的哪个部分会被绘制
- setEnabled(boolean enabled)` : 设置轴启用或禁用。如果false,该轴的任何部分都不会被绘制(不绘制坐标轴/便签等)
setDrawGridLines(boolean enabled)
: 设置为true,则绘制网格线。setDrawAxisLine(boolean enabled)
: 设置为true,则绘制该行旁边的轴线(axis-line)。setDrawLabels(boolean enabled)
: 设置为true,则绘制轴的标签。
设置数据
ChartData类
ChartData
类是所有数据类的基类,比如 LineData
,BarData
等,它是用来为 Chart
提供数据的,通过 setData(ChartData data){...}
方法。
Styling data
setDrawValues(boolean enabled)
: 启用/禁用 绘制所有DataSets
数据对象包含的数据的值文本。setValueTextColor(int color)
: 设置DataSets
数据对象包含的数据的值文本的颜色。setValueTextSize(float size)
: 设置DataSets
数据对象包含的数据的值文本的大小(单位是dp)。
详细使用的过程
线性图
-
创建布局
<com.github.mikephil.charting.charts.LineChart android:id="@+id/line_chart" android:layout_width="match_parent" android:layout_height="300dp" android:background="#ffffff" android:layout_margin="16dp"/>
-
实例化然后得到对象
-
准备线性图的点阵数据,可以存入显示多个折线图,只需要后面添加的时候加进去,Entry对象的变量第一个是轴坐标,第二个是y轴坐标
//这个是点的数据 ArrayList<Entry> values1 = new ArrayList<>(); //这个是点,将点的数据存入 values1.add(new Entry(4, 10)); values1.add(new Entry(6, 15)); values1.add(new Entry(9, 20));
-
折线对象
LineDataSet set1;
-
判断表中是否有数据,有就不改变对象地址的情况下追加
if (mLineCTable.getData() != null && mLineCTable.getData().getDataSetCount() > 0) { set1 = (LineDataSet) mLineCTable.getData().getDataSetByIndex(0);//0是指代第一条线 set1.setValues(values1); //刷新数据 mLineCTable.getData().notifyDataChanged(); mLineCTable.notifyDataSetChanged(); }
-
没有数据就向折线对象中添加参数,并且实例化折线
set1 = new LineDataSet(values1,"测试使用");
-
给折线对象设置一些杂七杂八的
//实例化折线对象,第一个参数是线的数据,第二个参数是线的标签 set1 = new LineDataSet(values1,"温度"); set1.setColor(Color.BLACK); set1.setCircleColor(Color.BLACK);//设置圆圈颜色 set1.setLineWidth(1f);//设置线宽 set1.setCircleRadius(3f);//设置焦点圆心的大小 // set1.enableDashedHighlightLine(10f, 5f, 0f);//点击后的高亮线的显示样式 // set1.setHighlightLineWidth(2f);//设置点击交点后显示高亮线宽 // set1.setHighlightEnabled(true);//是否禁用点击高亮线 // set1.setHighLightColor(Color.RED);//设置点击交点后显示交高亮线的颜色 set1.setValueTextSize(20f);//设置显示值的文字大小 set1.setDrawFilled(false);//设置禁用范围背景填充
-
设置x轴和y轴的显示
/** * 进行x轴和y轴的修改 */ XAxis xAxis = mLineCTable.getXAxis(); YAxis axisRight = mLineCTable.getAxisRight(); //x轴的显示位置 xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); axisRight.setEnabled(false); // x轴辅助线设置不显示 xAxis.setDrawGridLines(false);
-
格式化数据显示
//格式化显示数据 final DecimalFormat mFormat = new DecimalFormat("###,###,##0"); //设置数据格式器 set1.setValueFormatter(new IValueFormatter() { @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { //将参数转换为10进制 return mFormat.format(value); } }); //设置填充颜色 if (Utils.getSDKInt() >= 18) { // fill drawable only supported on api level 18 and above Drawable drawable = ContextCompat.getDrawable(this.getContext(), R.drawable.bg_splash); set1.setFillDrawable(drawable);//设置范围背景填充 } else { set1.setFillColor(Color.BLACK); }
-
将线对象存入表中
//保存LineDataSet集合 ArrayList<ILineDataSet> dataSets = new ArrayList<>(); dataSets.add(set1); // add the datasets
-
//创建LineData对象 属于LineChart折线图的数据集合 LineData data = new LineData(dataSets); // 添加到图表中 mLineCTable.setData(data); //绘制图表 mLineCTable.invalidate();
有关布局刷新的一些注意点
private ArrayList<Entry> values1 = new ArrayList<>();
//获取到这线的个对象
向线的对象中进行操作,追加点或者是删除点
values1.clear();
for (int i1 = 0; i1 < allData.size(); i1++) {
SensorDataBean sensorDataBean = allData.get(i1);
Log.i("123456", "run: " + sensorDataBean.getDate());
Float yfloat = Float.valueOf(sensorDataBean.getCo2());
Float xflot = (float) i1;
// 需要去除x轴时间的精度
values1.add(new Entry(xflot, yfloat));
}
更新视图
//需要更新视图
set1.notifyDataSetChanged();
mLineCTable.getLineData().notifyDataChanged();
mLineCTable.getData().notifyDataChanged();
mLineCTable.notifyDataSetChanged();
//注意!!!!!!!!!!!千万不能从子线程中更新视图,会报错
// android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Message message = new Message();
message.what =813;
handler.sendMessage(message);
//handle中执行了 mLineCTable.invalidate();
一定要注意刷新不能放在子线程中,我简直是脑淤血了写在线程中
关于X轴的格式化
其实很容易,只需要
//x轴格式转换
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
//这里绘制输入线的对应x轴的参数,需要返回x的显示参数
if (xTime.size()== 21){
return xTime.get((int) value);
}else {
return "刻度失效";
}
}
});
这里我把数据库的时间数据给提取出来了,并且给一起循环添加进了集合中
for (int i1 = 0; i1 < allData.size(); i1++) {
SensorDataBean sensorDataBean = allData.get(i1);
Float yfloat = Float.valueOf(sensorDataBean.getCo2());
Float xflot = (float) i1;
String dateFormat = new SimpleDateFormat("HH:mm:ss").format(sensorDataBean.getDate());
//将时间数据存入数组中
xTime.add(dateFormat);
// 需要去除x轴时间的精度
values1.add(new Entry(xflot, yfloat));
}
绘制的时候会回调getFormattedValue拿到对应刻度
全部的代码
package com.lenovo.smarttraffic.ui.fragment;
import android.graphics.Color;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
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.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
import com.lenovo.smarttraffic.R;
import com.lenovo.smarttraffic.mapping.SensorDataBean;
import com.lenovo.smarttraffic.ui.activity.ActivityWork1Activity;
import org.litepal.LitePal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import lecho.lib.hellocharts.model.Axis;
public class FragmentWork2VP extends Fragment {
private static final String TAG = "FragmentWork2VP";
private LineChart mLineCTable;
private boolean flag = true;
private ArrayList<Entry> values1 = new ArrayList<>();
private LineDataSet set1;
private ArrayList<ILineDataSet> dataSets;
private Handler handler;
private ArrayList<String> xTime = new ArrayList<>();
private String tableName = "光照度";
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.adapter_work2_vp, container, false);
initView(inflate);
initData();
return inflate;
}
private void initData() {
getLineData();
GetDataByDb();
handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
//ou pause Here
if (msg.what == 813) {
mLineCTable.invalidate();
}
return false;
}
});
}
private void GetDataByDb() {
//数据库读取出来
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
if (flag) {
List<SensorDataBean> allData = LitePal.findAll(SensorDataBean.class);
if (allData != null && allData.size() != 0) {
// Log.i("123456", "run: " + allData.toString());
values1.clear();
xTime.clear();
for (int i1 = 0; i1 < allData.size(); i1++) {
SensorDataBean sensorDataBean = allData.get(i1);
Float yfloat = Float.valueOf(sensorDataBean.getCo2());
Float xflot = (float) i1;
String dateFormat = new SimpleDateFormat("HH:mm:ss").format(sensorDataBean.getDate());
//将时间数据存入数组中
xTime.add(dateFormat);
// 需要去除x轴时间的精度
values1.add(new Entry(xflot, yfloat));
}
//需要更新视图
Log.i(TAG, "runq3123: " + values1.size());
if (values1.size() == allData.size()) {
set1.notifyDataSetChanged();
mLineCTable.getLineData().notifyDataChanged();
mLineCTable.notifyDataSetChanged();
//注意!!!!!!!!!!!千万不能从子线程中更新视图,会报错
// android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
Message message = new Message();
message.what = 813;
handler.sendMessage(message);
}
}
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread.start();
}
/**
*/
private void getLineData() {
//可以多点,但是我只需要一个点的数据
//这个是点的数据
values1.add(new Entry(0, 0));
//这个是一条连接线
//判断图标中是否有数据
if (mLineCTable.getData() != null && mLineCTable.getData().getDataSetCount() > 0) {
set1 = (LineDataSet) mLineCTable.getData().getDataSetByIndex(0);//0是指代第一条线
set1.setValues(values1);
//刷新数据
mLineCTable.getData().notifyDataChanged();
mLineCTable.notifyDataSetChanged();
} else {
//实例化折线对象,第一个参数是线的数据,第二个参数是线的标签
set1 = new LineDataSet(values1, tableName);
set1.setColor(Color.GRAY);
set1.setValueTextColor(Color.BLACK);
set1.setCircleColor(Color.GRAY);//设置圆圈颜色
set1.setLineWidth(3f);//设置线宽
set1.setCircleRadius(5f);//设置焦点圆心的大小
// set1.enableDashedHighlightLine(10f, 5f, 0f);//点击后的高亮线的显示样式
// set1.setHighlightLineWidth(2f);//设置点击交点后显示高亮线宽
// set1.setHighlightEnabled(true);//是否禁用点击高亮线
// set1.setHighLightColor(Color.RED);//设置点击交点后显示交高亮线的颜色
set1.setValueTextSize(15f);//设置显示值的文字大小
set1.setDrawFilled(false);//设置禁用范围背景填充
/**
* 进行x轴和y轴的修改
*/
XAxis xAxis = mLineCTable.getXAxis();
xAxis.setTextSize(15);
xAxis.setTextColor(Color.GRAY);
// xAxis.setAvoidFirstLastClipping(true);//让刻度显示全
xAxis.setLabelRotationAngle(+45);//反转刻度90度
xAxis.setLabelCount(21);//设置显示的标签数量
//x轴的显示位置
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
// x轴辅助线设置不显示
xAxis.setDrawGridLines(false);
YAxis yAxis = mLineCTable.getAxisLeft();
yAxis.setTextSize(15);
yAxis.setTextColor(Color.GRAY);
//y右轴的设置
mLineCTable.getAxisRight().setEnabled(false);
// TODO: 2020/9/15 这里需要进行数据格式转换 https://weeklycoding.com/mpandroidchart-documentation/formatting-data-values/
/**
* 格式化数据显示
*/
//设置线上的数据显示格式
final DecimalFormat mFormat = new DecimalFormat("###,###,##0");
//设置数据格式器
set1.setValueFormatter(new IValueFormatter() {
@Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
//将参数转换为10进制
return mFormat.format(value);
}
});
//
// final DecimalFormat mxFormat = new DecimalFormat("###,###,##0");
//x轴格式转换
xAxis.setValueFormatter(new IAxisValueFormatter() {
@Override
public String getFormattedValue(float value, AxisBase axis) {
//这里绘制输入线的对应x轴的参数,需要返回x的显示参数
if (xTime.size()== 21){
return xTime.get((int) value);
}else {
return "刻度失效";
}
}
});
//设置填充颜色
if (Utils.getSDKInt() >= 18) {
// fill drawable only supported on api level 18 and above
Drawable drawable = ContextCompat.getDrawable(this.getContext(), R.drawable.bg_splash);
set1.setFillDrawable(drawable);//设置范围背景填充
} else {
set1.setFillColor(Color.BLACK);
}
//将线存入表中
//保存LineDataSet集合
dataSets = new ArrayList<>();
dataSets.add(set1); // add the datasets
//创建LineData对象 属于LineChart折线图的数据集合
LineData data = new LineData(dataSets);
// 添加到图表中
mLineCTable.setData(data);
//绘制图表
mLineCTable.invalidate();
}
}
private void initView(View inflate) {
mLineCTable = (LineChart) inflate.findViewById(R.id.lineC_table);
}
}