Android图表控件MPAndroidChart——曲线图LineChart的使用(财富收益图)
目錄
前言
本文涉及文章
其他相關文章
1.數據準備
1.1 數據來源
2.曲線展示
2.1 MPAndroidChart獲取
2.2 數據對象獲取
2.3 數據展示
3.曲線完善
3.1 圖表背景、邊框、網格線修改
3.2 X Y軸值的自定義
3.3 線條的漸變背景、值、點的修改
3.4 MarkerView的實現
3.5 X軸的位置調整、以及X Y 軸的刻度顯示
4. 多條曲線
4.1 LineChart創建多條曲線
4.2 MarkerView顯示所以曲線的X Y 軸值
5. 重置某條曲線
6. 最終效果圖
前言
發現最新的MPAndroidChart和以前版本的使用有一些差距,就寫下了現在新版的使用方法
注:2018-06-01更新,當前MPAndroidChart版本:3.0.3?
本文涉及文章
Android圖表控件MPAndroidChart的簡單介紹(MPAndroidChart3.0)
Android圖表控件MPAndroidChart——LineChart實現 X、Y軸以及原點線的直尺刻度樣式
其他相關文章
Android圖表控件MPAndroidChart——曲線圖LineChart的使用(多條曲線)
Android圖表控件MPAndroidChart——曲線圖LineChart(多條曲線)動態添加數據
Android圖表控件MPAndroidChart——柱狀圖BarChart的使用(多條柱狀圖)
Android圖表控件MPAndroidChart——曲線圖+柱狀圖 CombinedChart的使用?
本文將要實現的圖表效果,個人財富收益圖。
1.數據準備
1.1 數據來源
數據是抓包傭金寶的數據,將獲取的數據存入.json文件。
json格式如下
Json 文件地址:
https://github.com/897532167/ChartManager/blob/master/app/src/main/assets/line_chart.json
2.曲線展示
2.1 MPAndroidChart獲取
Github 地址:https://github.com/PhilJay/MPAndroidChart
依賴:
Project 的build.gradle文件中添加
allprojects {
? ? repositories {
? ? ? ? maven { url 'https://jitpack.io' }
? ? }
}
然后在 module中的build,gradle 中添加
implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3'
然而大多情況下,我們會根據自己的需求自定義MPAndroidChart庫,則需要下載源碼并將MPChartLib引入自己的項目中。
2.2 數據對象獲取
在Android Studio app項目src同級目錄下新建中新建assets文件夾,然后將步驟1.1得到的.json文件放入改文件夾中。
然后在獲取.json文件中的json字符串并解析為對應的數據對象,可參考以下文章
相關文章:Android訪問assets本地Json文件
在此就不詳敘述了,只是列出圖表展示所需要的類
/**
?* 我的收益
?*/
public class IncomeBean {
? ? /**
? ? ?* tradeDate : 20180502
? ? ?* value : 0.03676598
? ? ?*/
? ? private String tradeDate;
? ? private double value;
}
?
/**
?* 滬深創指數
?*/
public class CompositeIndexBean {
? ? /**
? ? ?* rate : -0.00034196
? ? ?* tradeDate : 20180502
? ? ?*/
? ? private String rate;
? ? private String tradeDate;
}
2.3 數據展示
2.3.1??LineChart 圖表初始化設置
LineChart曲線圖表一會使用到如下屬性
? ? private LineChart lineChart;
? ? private XAxis xAxis; ? ? ? ? ? ? ? ?//X軸
? ? private YAxis leftYAxis; ? ? ? ? ? ?//左側Y軸
? ? private YAxis rightYaxis; ? ? ? ? ? //右側Y軸
? ? private Legend legend; ? ? ? ? ? ? ?//圖例
? ? private LimitLine limitLine; ? ? ? ?//限制線
// ?private MyMarkerView markerView; ? ?//標記視圖 即點擊xy軸交點時彈出展示信息的View 需自定義
然后進行相應的設置
/**
?* 初始化圖表
?*/
private void initChart(LineChart lineChart) {
? ? /***圖表設置***/
? ? //是否展示網格線
? ? lineChart.setDrawGridBackground(false);
? ? //是否顯示邊界
? ? lineChart.setDrawBorders(true);
? ? //是否可以拖動
? ? lineChart.setDragEnabled(false);
? ? //是否有觸摸事件
? ? lineChart.setTouchEnabled(true);
? ? //設置XY軸動畫效果
? ? lineChart.animateY(2500);
? ? lineChart.animateX(1500);
?
? ? /***XY軸的設置***/
? ? xAxis = lineChart.getXAxis();
? ? leftYAxis = lineChart.getAxisLeft();
? ? rightYaxis = lineChart.getAxisRight();
? ? //X軸設置顯示位置在底部
? ? xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
? ? xAxis.setAxisMinimum(0f);
? ? xAxis.setGranularity(1f);
? ? //保證Y軸從0開始,不然會上移一點
? ? leftYAxis.setAxisMinimum(0f);
? ? rightYaxis.setAxisMinimum(0f);
?
? ? /***折線圖例 標簽 設置***/
? ? legend = lineChart.getLegend();
? ? //設置顯示類型,LINE CIRCLE SQUARE EMPTY 等等 多種方式,查看LegendForm 即可
? ? legend.setForm(Legend.LegendForm.LINE);
? ? legend.setTextSize(12f);
? ? //顯示位置 左下方
? ? legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
? ? legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
? ? legend.setOrientation(Legend.LegendOrientation.HORIZONTAL);
? ? //是否繪制在圖表里面
? ? legend.setDrawInside(false);
}
2.3.2 LineDataSet 曲線初始化設置
/**
?* 曲線初始化設置 一個LineDataSet 代表一條曲線
?*
?* @param lineDataSet 線條
?* @param color ? ? ? 線條顏色
?* @param mode
?*/
private void initLineDataSet(LineDataSet lineDataSet, int color, LineDataSet.Mode mode) {
? ? lineDataSet.setColor(color);
? ? lineDataSet.setCircleColor(color);
? ? lineDataSet.setLineWidth(1f);
? ? lineDataSet.setCircleRadius(3f);
? ? //設置曲線值的圓點是實心還是空心
? ? lineDataSet.setDrawCircleHole(false);
? ? lineDataSet.setValueTextSize(10f);
? ? //設置折線圖填充
? ? lineDataSet.setDrawFilled(true);
? ? lineDataSet.setFormLineWidth(1f);
? ? lineDataSet.setFormSize(15.f);
? ? if (mode == null) {
? ? ? ? //設置曲線展示為圓滑曲線(如果不設置則默認折線)
? ? ? ? lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
? ? } else {
? ? ? ? lineDataSet.setMode(mode);
? ? }
}
2.3.3??曲線展示
/**
?* 展示曲線
?*
?* @param dataList 數據集合
?* @param name ? ? 曲線名稱
?* @param color ? ?曲線顏色
?*/
public void showLineChart(List<IncomeBean> dataList, String name, int color) {
? ? List<Entry> entries = new ArrayList<>();
? ? for (int i = 0; i < dataList.size(); i++) {
? ? ? ? IncomeBean data = dataList.get(i);
? ? ? ? /**
? ? ? ? ?* 在此可查看 Entry構造方法,可發現 可傳入數值 Entry(float x, float y)
? ? ? ? ?* 也可傳入Drawable, Entry(float x, float y, Drawable icon) 可在XY軸交點 設置Drawable圖像展示
? ? ? ? ?*/
? ? ? ? Entry entry = new Entry(i, (float) data.getValue());
? ? ? ? entries.add(entry);
? ? }
? ? // 每一個LineDataSet代表一條線
? ? LineDataSet lineDataSet = new LineDataSet(entries, name);
? ? initLineDataSet(lineDataSet, color, LineDataSet.Mode.LINEAR);
? ? LineData lineData = new LineData(lineDataSet);
? ? lineChart.setData(lineData);
}
然后在Activity中調用
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
? ? super.onCreate(savedInstanceState);
? ? setContentView(R.layout.activity_line_chart);
? ? lineChart = findViewById(R.id.lineChart);
? ? initChart(lineChart);
? ? LineChartBean lineChartBean = LocalJsonAnalyzeUtil.JsonToObject(this,
? ? ? ? ? ? "chart.json", LineChartBean.class);
? ? List<IncomeBean> list = lineChartBean.getGRID0().getResult().getClientAccumulativeRate();
? ? showLineChart(list, "我的收益", Color.CYAN);
}
注意:不了解數據怎么來的可查看?相關文章:Android訪問assets本地Json文件?或者本文相關代碼
此時的圖形效果
線性圖是有了,但離需要達到的效果差了很多很多,所有需要一點點的完善。
3.曲線完善
首先總結哪里需要進行修改完善,然后一一進行修改,需要的修改的地方如下。
圖表背景、邊框、網格的修改
X Y軸值的自定義
線條的漸變背景、值、點 的修改
MarkerView的實現
X軸的位置、X Y 軸的刻度展示(需要修改源碼、放最后來處理)
3.1 圖表背景、邊框、網格線修改
修改背景,去掉邊框
lineChart.setBackgroundColor(Color.WHITE);
//是否顯示邊界
lineChart.setDrawBorders(false);
網格線修改
在2.3.1步的我們已經設置了禁止顯示網格線
//是否展示網格線
lineChart.setDrawGridBackground(false);
但還是顯示了網格線,而且不是我們想要的?虛線 。其實那是 X Y軸自己的網格線,禁掉即可
xAxis.setDrawGridLines(false);
rightYaxis.setDrawGridLines(false);
leftYAxis.setDrawGridLines(true);
設置X Y軸網格線為虛線(實體線長度、間隔距離、偏移量:通常使用 0)
leftYAxis.enableGridDashedLine(10f, 10f, 0f);
目標效果圖沒有右側Y軸,所以去掉右側Y軸
rightYaxis.setEnabled(false);
現在的效果圖
3.2 X Y軸值的自定義
目標圖的效果是 X軸顯示日期,Y軸顯示百分比而且均分10份
數據獲取到的時間為 20180502 我們需要顯示 05-02 所以需要進行日期轉換
一個日期轉換工具
public class DateUtil {
?
? ? public static String formatDate(String str) {
? ? ? ? SimpleDateFormat sf1 = new SimpleDateFormat("yyyyMMdd");
? ? ? ? SimpleDateFormat sf2 = new SimpleDateFormat("MM-dd");
? ? ? ? String formatStr = "";
? ? ? ? try {
? ? ? ? ? ? formatStr = sf2.format(sf1.parse(str));
? ? ? ? } catch (ParseException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return formatStr;
? ? }
}
X軸值的定義
在?showLineChart 方法中我們會傳入X軸的值,所以自定義X軸的值可以 寫在該方法內
xAxis.setValueFormatter(new IAxisValueFormatter() {
? ? @Override
? ? public String getFormattedValue(float value, AxisBase axis) {
? ? ? ? String tradeDate = dataList.get((int) value % dataList.size()).getTradeDate();
? ? ? ? return DateUtil.formatDate(tradeDate);
? ? }
});
注:目標圖的數據是5月2日到5月28日,而本文所使用的數據是5月2日至5月25日。且數據日期是不包含周末的
X軸的間隔的實現,數據一共有18條,目標圖是按照3天一間隔(因為無周末數據的關系,日期上看可能不是那樣)
設置X軸分割數量
xAxis.setLabelCount(6,false);
true代表強制均分,可能會導致數據顯示不均勻
Y軸值的自定義
與X軸值得自定義類似,并按照目標圖的分割要求一樣 將Y軸分為 8份
leftYAxis.setValueFormatter(new IAxisValueFormatter() {
? ? @Override
? ? public String getFormattedValue(float value, AxisBase axis) {
? ? ? ? return ((int) (value * 100)) + "%";
? ? }
});
leftYAxis.setLabelCount(8);
然后此時的效果
3.3 線條的漸變背景、值、點的修改
線條漸變線
新建一個方法
/**
?* 設置線條填充背景顏色
?*
?* @param drawable
?*/
public void setChartFillDrawable(Drawable drawable) {
? ? if (lineChart.getData() != null && lineChart.getData().getDataSetCount() > 0) {
? ? ? ? LineDataSet lineDataSet = (LineDataSet) lineChart.getData().getDataSetByIndex(0);
? ? ? ? //避免在 initLineDataSet()方法中 設置了 lineDataSet.setDrawFilled(false); 而無法實現效果
? ? ? ? lineDataSet.setDrawFilled(true);
? ? ? ? lineDataSet.setFillDrawable(drawable);
? ? ? ? lineChart.invalidate();
? ? }
}
然后?drawable 文件中 創建漸變樣式?fade_blue.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
? ? <gradient
? ? ? ? android:angle="90"
? ? ? ? android:endColor="#FF6FA9E1"
? ? ? ? android:startColor="#00ff0000" />
</shape>
再調用該方法
showLineChart(list, "我的收益", getResources().getColor(R.color.blue));
Drawable drawable = getResources().getDrawable(R.drawable.fade_blue);
setChartFillDrawable(drawable);
線條點和值的更改
不顯示點,在 initLineDataSet方法中添加
lineDataSet.setDrawCircles(false);
線條值的更改
目標圖的效果是不顯示 值,但有時候還是會要求顯示值,而且還要求更高 線條X值的顯示內容?
所以在此介紹一下更改 曲線顯示自定義X值的內容?
lineDataSet.setValueFormatter(new IValueFormatter() {
? ? @Override
? ? public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
? ? ? ? DecimalFormat df = new DecimalFormat(".00");?
? ? ? ? return df.format(value * 100) + "%";
? ? }
});
會發現只要是自定義 值的顯示內容 都是Chart對應的部分.setValueFormatter()。
現在的效果(修改了寬高)
不顯示值
lineDataSet.setDrawValues(false);
3.4 MarkerView的實現
要求是點擊曲線的點,然后彈出一個View 顯示當前的日期,以及我的收益
即 MarkView 顯示X Y 軸的值
1.搭建MarkView的布局文件?layout_markview
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
? ? android:layout_width="wrap_content"
? ? android:layout_height="wrap_content"
? ? android:background="@drawable/shape_square"
? ? android:orientation="vertical">
?
? ? <TextView
? ? ? ? android:id="@+id/tv_date"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:textColor="@android:color/white" />
?
? ? <TextView
? ? ? ? android:id="@+id/tv_value"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:layout_marginTop="5dp"
? ? ? ? android:textColor="@android:color/white" />
?
</LinearLayout>
其中背景 shape_square.xml 是圓角透明灰背景
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
? ? <corners android:radius="5dp" />
? ? <stroke
? ? ? ? android:width="1px"
? ? ? ? android:color="@color/transparent_gray" />
? ? <solid android:color="@color/transparent_gray" />
? ? <padding
? ? ? ? android:bottom="5dp"
? ? ? ? android:left="5dp"
? ? ? ? android:right="5dp"
? ? ? ? android:top="5dp" />
</shape>
2.自定義MarkerView
public class LineChartMarkView extends MarkerView {
?
? ? private TextView tvDate;
? ? private TextView tvValue;
? ? private IAxisValueFormatter xAxisValueFormatter;
? ? DecimalFormat df = new DecimalFormat(".00");
?
? ? public LineChartMarkView(Context context, IAxisValueFormatter xAxisValueFormatter) {
? ? ? ? super(context, R.layout.layout_markview);
? ? ? ? this.xAxisValueFormatter = xAxisValueFormatter;
?
? ? ? ? tvDate = findViewById(R.id.tv_date);
? ? ? ? tvValue = findViewById(R.id.tv_value);
? ? }
?
? ? @SuppressLint("SetTextI18n")
? ? @Override
? ? public void refreshContent(Entry e, Highlight highlight) {
? ? ? ? //展示自定義X軸值 后的X軸內容
? ? ? ? tvDate.setText(xAxisValueFormatter.getFormattedValue(e.getX(), null));
? ? ? ? tvValue.setText("我的收益:" + df.format(e.getY() * 100) + "%");
? ? ? ? super.refreshContent(e, highlight);
? ? }
?
? ? @Override
? ? public MPPointF getOffset() {
? ? ? ? return new MPPointF(-(getWidth() / 2), -getHeight());
? ? }
}
注:這種方式是顯示自定義X軸值后的 x軸內容,只是靠e.getX()得到的float類型,無法滿足我們的要求
3.設置MarkView
/**
?* 設置 可以顯示X Y 軸自定義值的 MarkerView
?*/
public void setMarkerView() {
? ? LineChartMarkView mv = new LineChartMarkView(this, xAxis.getValueFormatter());
? ? mv.setChartView(lineChart);
? ? lineChart.setMarker(mv);
? ? lineChart.invalidate();
}
調用該方法即可
此時的效果
3.5 X軸的位置調整、以及X Y 軸的刻度顯示
X Y 軸的刻度顯示,以及位置調整可查看我的另一篇文章
相關文章:Android圖表控件MPAndroidChart——LineChart實現 X、Y軸以及原點線的直尺刻度樣式
發現圖表的右下角還有一個描述標簽 Descripition Lable 需要在LineChart初始化時設置一下
? ? ? ? Description description = new Description();
// ? ? ? ?description.setText("需要展示的內容");
? ? ? ? description.setEnabled(false);
? ? ? ? lineChart.setDescription(description);
此時的效果
4. 多條曲線
當前只是實現了展示一條曲線,而目標圖需要實現兩條(多條曲線)
4.1 LineChart創建多條曲線
前面說過 一個LineDataSet就是一條曲線,需要兩條曲線的時候 在創建一個LineDataSet 添加進去即可
/**
?* 添加曲線
?*/
private void addLine(List<CompositeIndexBean> dataList, String name, int color) {
? ? List<Entry> entries = new ArrayList<>();
? ? for (int i = 0; i < dataList.size(); i++) {
? ? ? ? CompositeIndexBean data = dataList.get(i);
? ? ? ? Entry entry = new Entry(i, (float) data.getRate());
? ? ? ? entries.add(entry);
? ? }
? ? // 每一個LineDataSet代表一條線
? ? LineDataSet lineDataSet = new LineDataSet(entries, name);
? ? initLineDataSet(lineDataSet, color, LineDataSet.Mode.LINEAR);
? ? lineChart.getLineData().addDataSet(lineDataSet);
? ? lineChart.invalidate();
}
然后調用改方法即可,也可以在 showLineChart方法中 創建兩條曲線。
showLineChart(list, "我的收益", getResources().getColor(R.color.blue));
?
List<CompositeIndexBean> indexBeanList = lineChartBean.getGRID0().getResult().getCompositeIndexShanghai();
addLine(indexBeanList, "上證指數", getResources().getColor(R.color.orange));
此時的效果
4.2 MarkerView顯示所以曲線的X Y 軸值
現在兩條曲線了,前面MarkerView只是顯示的?我的收益?的數據。現在需要顯示所有曲線的的值
也就是在MarkerView 的 refreshContent中需要獲取到我們展示的數據。
兩種方式可以實現:
一:通過MarkerView構造方法 傳入我們所展示的數據的集合?
二:通過MarkerView 獲取到當前的LineChart,然后通過LineChart獲取LineData,圖表展示的數據 都在LineData中可以得到
采用方式二比較方便,代碼如下:
public class LineChartMarkView extends MarkerView {
?
? ? private TextView tvDate;
? ? private TextView tvValue0;
? ? private TextView tvValue1;
? ? private IAxisValueFormatter xAxisValueFormatter;
? ? DecimalFormat df = new DecimalFormat("0.00");
?
? ? public LineChartMarkView(Context context, IAxisValueFormatter xAxisValueFormatter) {
? ? ? ? super(context, R.layout.layout_markview);
? ? ? ? this.xAxisValueFormatter = xAxisValueFormatter;
? ? ? ? tvDate = (TextView) findViewById(R.id.tv_date);
? ? ? ? tvValue0 = (TextView) findViewById(R.id.tv_value0);
? ? ? ? tvValue1 = (TextView) findViewById(R.id.tv_value1);
? ? }
?
? ? @SuppressLint("SetTextI18n")
? ? @Override
? ? public void refreshContent(Entry e, Highlight highlight) {
? ? ? ? Chart chart = getChartView();
? ? ? ? if (chart instanceof LineChart) {
? ? ? ? ? ? LineData lineData = ((LineChart) chart).getLineData();
? ? ? ? ? ? //獲取到圖表中的所有曲線
? ? ? ? ? ? List<ILineDataSet> dataSetList = lineData.getDataSets();
? ? ? ? ? ? for (int i = 0; i < dataSetList.size(); i++) {
? ? ? ? ? ? ? ? LineDataSet dataSet = (LineDataSet) dataSetList.get(i);
? ? ? ? ? ? ? ? //獲取到曲線的所有在Y軸的數據集合,根據當前X軸的位置 來獲取對應的Y軸值
? ? ? ? ? ? ? ? float y = dataSet.getValues().get((int) e.getX()).getY();
? ? ? ? ? ? ? ? if (i == 0) {
? ? ? ? ? ? ? ? ? ? tvValue0.setText(dataSet.getLabel() + ":" + df.format(y * 100) + "%");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (i == 1) {
? ? ? ? ? ? ? ? ? ? tvValue1.setText(dataSet.getLabel() + ":" + df.format(y * 100) + "%");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? tvDate.setText(xAxisValueFormatter.getFormattedValue(e.getX(), null));
? ? ? ? }
? ? ? ? super.refreshContent(e, highlight);
? ? }
?
? ? @Override
? ? public MPPointF getOffset() {
? ? ? ? return new MPPointF(-(getWidth() / 2), -getHeight());
? ? }
}
此時的圖表
5. 重置某條曲線
經過前面的幾步圖表是基本完成了,就差底部的切換按鈕以及曲線重置了。
布局代碼在此就不展示了,詳細代碼請看文本 本文相關代碼。在此列出重置曲線方法的代碼
public void resetLine(int position, List<CompositeIndexBean> dataList, String name, int color) {
? ? LineData lineData = lineChart.getData();
? ? List<ILineDataSet> list = lineData.getDataSets();
? ? if (list.size() <= position) {
? ? ? ? return;
? ? }
?
? ? List<Entry> entries = new ArrayList<>();
? ? for (int i = 0; i < dataList.size(); i++) {
? ? ? ? CompositeIndexBean data = dataList.get(i);
? ? ? ? Entry entry = new Entry(i, (float) data.getRate());
? ? ? ? entries.add(entry);
? ? }
?
? ? LineDataSet lineDataSet = new LineDataSet(entries, name);
? ? initLineDataSet(lineDataSet, color, LineDataSet.Mode.LINEAR);
?
? ? lineData.getDataSets().set(position, lineDataSet);
? ? lineChart.invalidate();
}
調用該方法,將第二條曲線設置為深證指數
shenzheng = lineChartBean.getGRID0().getResult().getCompositeIndexShenzhen();
resetLine(1, shenzheng, "深證指數", getResources().getColor(R.color.orange));
設置不顯示曲線名稱(圖例)Legend
legend.setEnabled(false);
6. 最終效果圖
本文代碼:https://github.com/897532167/ChartManager
繪制刻度線:Android圖表控件MPAndroidChart——LineChart實現 X、Y軸以及原點線的直尺刻度樣式
---------------------?
原文:https://blog.csdn.net/ww897532167/article/details/74129478?
?
總結
以上是生活随笔為你收集整理的Android图表控件MPAndroidChart——曲线图LineChart的使用(财富收益图)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 职业程序员培养之道
- 下一篇: Android资源文件在配置文件中的使用