If you want to display the graph on the Android app, MPAndroidChart Library is often used. (iOS version of ** Charts Library ** also exists)
It's a great library with many features and a great UI, Due to the lack of Japanese information, I feel that the implementation difficulty is quite high. So, ** I created an additional package to easily create a graph! ** ** Github
You can easily create a graph like the one below
(The subject is heavy! (Laughs))
** This package is premised on implementation in Kotlin, If you wish, I will make a Java / Swift (iOS) version. If you have any other questions or requests to add methods, please feel free to comment! ** **
The following parts I struggled with when creating an app that included graphs on the MPAndroidChart. ** 1. Creating a time series graph ** ** 2. Format specification (especially color) ** ** 3. Creating tooltips ** ** 4. There are few Japanese documents **
[Details will be written in the supplement](https://qiita.com/c60evaporator/items/b8f8c83dd3630c0091cf#mpandroidchart%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B% E6% 99% 82% E7% B3% BB% E5% 88% 97% E3% 82% B0% E3% 83% A9% E3% 83% 95% E3% 81% AE% E4% BD% 9C% E3% 82% 8A% E6% 96% B9), It takes a lot of time and effort to store data and format axes to create a time series graph.
We have created a method dedicated to time series graphs so that it can be created with simple operations.
Also, if the time is not evenly spaced as shown below,
val x = listOf<Date>(
sdf.parse("2020/09/01 00:00:00"),
sdf.parse("2020/09/01 06:00:00"),
sdf.parse("2020/09/01 12:00:00"),
sdf.parse("2020/09/01 18:00:00"),
sdf.parse("2020/09/02 00:00:00"),
sdf.parse("2020/09/02 06:00:00"),
sdf.parse("2020/09/02 12:00:00"),
sdf.parse("2020/09/03 18:00:00"),//Only here the time interval is flying
)
With the above method, it will be plotted at equal intervals based only on the index information. The time interval is not accurately represented on the horizontal axis.
In this package, we also prepared a display mode that plots accurately even if the horizontal axis is not evenly spaced. (Labels are displayed only at the beginning and end)
In MPAndroidChart, roughly for graph display ** ① Data input process ** ** ② Process to specify UI format ** Two types are required. From the standpoint of independence, it is desirable to be able to specify these two types of processing separately in the code.
However, when specifying multiple Y-axis values like a line graph, As shown below, it will be a specification method in which processing is complicated in ① and ②.
//Data storage in Entry → ① Data input processing
var entryList1 = mutableListOf<Entry>()//1st line
var entryList2 = mutableListOf<Entry>()//Second line
for(i in x.indices){
entryList1.add(
Entry(x[i], y1[i])
)
entryList2.add(
Entry(x[i], y2[i])
)
}
//X-axis setting → ② UI format specification processing
lineChart.xAxis.apply {
isEnabled = true
textColor = Color.BLACK
}
//Left Y-axis setting → ② UI format specification processing
lineChart.axisLeft.apply {
isEnabled = true
textColor = Color.BLACK
}
//Right Y-axis setting → ② UI format specification processing
lineChart.axisLeft.apply {
isEnabled = false
}
//LineDataSet(For each line)Create a list of → ① Data entry process
val lineDataSets = mutableListOf<ILineDataSet>()
//Data storage for the first line → ① Data input processing
val lineDataSet1 = LineDataSet(entryList1, "linear")
//Color of the first line → ② UI format specification processing
lineDataSet1.color = Color.BLUE
//Store in list → ① Data entry processing
lineDataSets.add(lineDataSet1)
//Data storage for the second line → ① Data input processing
val lineDataSet2 = LineDataSet(entryList2, "square")
//The color of the second line → ② UI format specification processing
lineDataSet2.color = Color.RED
//Store LineDataSet list in LineData → ① Data input processing
lineDataSets.add(lineDataSet2)
//Data storage in LineChart → ① Data input processing
lineChart.data = LineData(lineDataSets)
Since the above specification method is not preferable from the viewpoint of independence and code readability, **-UI format specification class (Chart and DataSet. See here for the difference between them](https://qiita.com/c60evaporator/items/14e63d22d860b73e6f22#%E3%83%95%E3%82% A9% E3% 83% BC% E3% 83% 9E% E3% 83% 83% E3% 83% 88% E6% 8C% 87% E5% AE% 9A% E3% 81% 8C2% E3% 81% 8B% E6% 89% 80% E3% 81% AB% E5% 88% 86% E3% 81% 8B% E3% 82% 8C% E3% 82% 8B)) ** **-Data entry method ** **-Method to draw a graph based on the above UI specification & data ** The configuration is such that it can be specified independently in the order of.
Also, ** I don't know how to specify the format! For those who say ** Even if you do not specify the format (do not put an argument in the constructor) I've added a function that makes my subjectivity feel good (abstract expression, but ... lol).
In particular, there are many setting points for color setting, and manual setting is troublesome, so **-Automatically specify the color of lines and bars based on Color Universal Design ** ** ・ When the background is black (brightness is 0.5 or less), the characters are automatically changed to white **
Added the function
"Tooltip" that displays the details of the data when you tap the data point
If there is, the visibility of the UI will be greatly improved.
However, the Official Documentation does not properly describe the implementation method. It is required to implement by groping while looking at the sample code.
The following can be specified in the format specification class so that tooltips can be displayed easily. ** A. Whether to display tooltips ** Specifies whether to display tooltips
** B. Axial direction of data to be displayed (both X, Y, XY) ** Select the axial direction of the data to be displayed as shown in the figure below (from left: no display, X only, Y only, XY both)
** C. For time series graphs, time display format (eg "M / d HH: mm") ** Enabled to specify the time display format when the X axis is time series. In the figure below, the format "d day H hour" is specified.
** D. Units given to data (eg ° C,%, Pa, etc.) ** Units can be added to the displayed data for both the X-axis and Y-axis. In the figure below, the unit "circle" is added to the Y axis.
It can be said that there are no articles that are comprehensively explained in Japanese. Especially for UI format specification system, there are many method properties whose explanation is not described in the official English document.
In this article, I have provided a list of UI format specification properties and a link that illustrates the changes due to the specification](https://qiita.com/c60evaporator/items/b8f8c83dd3630c0091cf#%E3%82%B0%E3%83 % A9% E3% 83% 95% E5% 85% A8% E4% BD% 93chart% E3% 81% AB% E9% 81% A9% E7% 94% A8% E3% 81% 99% E3% 82% 8Bui % E3% 83% 95% E3% 82% A9% E3% 83% BC% E3% 83% 9E% E3% 83% 83% E3% 83% 88% E4% B8% 80% E8% A6% A7) ([Click here for a list of DataSet UI format specification properties](https://qiita.com/c60evaporator/items/b8f8c83dd3630c0091cf#%E3%82%AB%E3%83%86%E3%82%B4%E3%83% AA% E3% 81% 94% E3% 81% A8dataset% E3% 81% AB% E9% 81% A9% E7% 94% A8% E3% 81% 99% E3% 82% 8Bui% E3% 83% 95% E3% 82% A9% E3% 83% BC% E3% 83% 9E% E3% 83% 83% E3% 83% 88% E4% B8% 80% E8% A6% A7))
Which property should be set and how the graph shape will change I think you can easily follow it with Japanese + images
Please build the following development environment ** ・ Development PC (Windows 10 is used this time) ** **-Android Studio (4.0.1 is used this time, Android version is recommended after API26) ** **-Android smartphone to operate (Pixel 3a is used this time) **
The procedure is as follows ** 1. Introduction of MPAndroidChart ** ** 2. Introduction of CustomMP Android Chart package **
Introduce MPAndroidChart, a graph drawing library, in the project
In build.gradle (Project),
allprojects {
repositories{
:
maven { url 'https://jitpack.io' }
:
I will add the description.
In build.gradle (Module: app),
dependencies {
:
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
:
I will add the description.
If you close and reopen the project with "File → Close Project" on the menu bar, The library is reflected.
A collection of methods and classes for easily creating the above MPAndroidChart graph, Packaged as "Custom MP Android Chart". Uploaded to Github
It consists of the following 6 modules ** ・ LineChartMethods.kt **: Method collection for line graphs ** ・ BarChartMethods.kt **: Method collection for bar graphs ** ・ CandleStickChartMethods.kt **: A collection of methods for candlestick graphs (graphs like stock price charts) ** ・ PieChartMethods.kt **: Method collection for line graphs ** ・ MarkerViews.kt **: Tooltip display class ** ・ ChartFormats.kt **: Module that collects UI format specification classes
Also, the layout file used in the tooltip You also need to install ** simple_marker_view.xml **.
Follow the steps below to install it in the project to create the graph. ** * There are many manual operations, so if you know a better way to provide it, I would appreciate it if you could teach me **
Right-click on the package folder directly under the java folder, select New → Package and name it "chart"
Right-click on the chart folder created above, select New → Kotlin File / Class, name it "LineChartMethods", and select LineChartMethods.kt on GitHub. Copy (/ master / app / src / main / java / com / mongodb / custommpandroidchart / chart).
Right-click on the chart folder created above, select New → Kotlin File / Class, name it "BarChartMethods", and select BarChartMethods.kt on GitHub. Copy (/ master / app / src / main / java / com / mongodb / custommpandroidchart / chart).
Right-click on the chart folder you created above, select New → Kotlin File / Class, name it "CandleStickChartMethods", and select CandleStickChartMethods.kt on GitHub. Copy (/ master / app / src / main / java / com / mongodb / custommpandroidchart / chart).
Right-click on the chart folder you created above, select New → Kotlin File / Class, name it "PieChartMethods", and select PieChartMethods.kt on GitHub. Copy (/ master / app / src / main / java / com / mongodb / custommpandroidchart / chart).
Right-click on the chart folder created above, select New → Kotlin File / Class, name it "MarkerViews", and select MarkerViews.kt on GitHub Copy (/ master / app / src / main / java / com / mongodb / custommpandroidchart / chart).
Right-click on the chart folder created above, select New → Kotlin File / Class, name it "ChartFormats", and select ChartFormats.kt on GitHub. Copy (/ master / app / src / main / java / com / mongodb / custommpandroidchart / chart).
Follow the steps below to create a layout file for tooltips when clicking.
Right-click res / layout, select New → Layout Resource File and name it "simple_marker_view"
Rewrite the created xml file with the following contents
simple_marker_view.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="@color/toolTipBgColor"
tools:ignore="Overdraw">
<TextView
android:id="@+id/tvSimple"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="7dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:text=""
android:textSize="12sp"
android:textColor="@color/toolTipTextColor"
android:ellipsize="end"
android:gravity="center_vertical|center_horizontal"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
Add the following contents to res / values / colors.xml. (Please change the color code see here as appropriate)
colors.xml
:
<color name="toolTipBgColor">#999999</color>//Background color code
<color name="toolTipTextColor">#ffffff</color>//Text color code
:
This completes the package installation.
For line graphs, bar graphs, candlestick graphs, and pie charts, I will explain the implementation method.
The implementation method of the line graph is explained separately for the layout (.xml) and the processing section (.kt).
Include the widget for LineChart in the layout (eg activity_main.xml) as shown below.
activity_main.xml
:
<com.github.mikephil.charting.charts.LineChart
android:id="@+id/lineChartExample"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
:
Implement the process of calling the line graph creation method in the Kotlin file (eg MainActivity.kt). ・ When there is only one line ・ When you want to make the horizontal axis time series ・ When there are multiple I will explain each example separately.
As a basic flow **-Chart format specification ** **-Specify DataSet format ** ** ・ Data is stored in Entry with makeLineChartData method ** **-Draw a graph with the setupLineChart method ** It will be.
//Creation of sample data for display//
val x = listOf<Float>(1f, 2f, 3f, 5f, 8f, 13f, 21f, 34f)//X-axis data
val y = x.map{it*it}//Y-axis data (X-axis squared)
//Chart format
var lineChartFormat = LineChartFormat(/*Chart format specification here*/)
//DataSet format(Category name Map)
var lineDataSetFormat = mapOf(
"linear" to LineDataSetFormat(/*Specify DataSet format here*/)
)
//① Data storage in Entry(Category name Map)
val allLinesEntries: MutableMap<String, MutableList<Entry>> = mutableMapOf(
"linear" to makeLineChartData(x, y)
)
//② ~ ⑦ Graph creation
setupLineChart(allLinesEntries, findViewById(R.id.lineChartExample), lineChartFormat, lineDataSetFormat, context)
The Chart format and DataSet format specify the UI of the graph. [Details will be described later](https://qiita.com/c60evaporator/items/b8f8c83dd3630c0091cf#ui%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3% 83% 83% E3% 83% 88% E3% 81% AE% E6% 8C% 87% E5% AE% 9A% E6% 96% B9% E6% B3% 95) When you run the above code, you will see a graph like the one below
If you want to make the horizontal axis time series, use the method to store data in Entry. makeLineChartData() → makeDateLineChartData() Change to
//Creation of sample data for display//
//X-axis data(time)
val sdf: SimpleDateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
val x = listOf<Date>(
sdf.parse("2020/09/01 00:00:00"),
sdf.parse("2020/09/01 06:00:00"),
sdf.parse("2020/09/01 12:00:00"),
sdf.parse("2020/09/01 18:00:00"),
sdf.parse("2020/09/02 00:00:00"),
sdf.parse("2020/09/02 06:00:00"),
sdf.parse("2020/09/02 12:00:00"),
sdf.parse("2020/09/03 18:00:00"),
)
val y = listOf<Float>(1f, 2f, 3f, 5f, 8f, 13f, 21f, 34f)//Y-axis data(Numerical value)
//Chart format
var lineChartFormat = LineChartFormat(/*Chart format specification here*/)
//DataSet format(Category name Map)
var lineDataSetFormat = mapOf(
"linear" to LineDataSetFormat(/*Specify DataSet format here*/)
)
//① Data storage in Entry(Category name Map)
val allLinesEntries: MutableMap<String, MutableList<Entry>> = mutableMapOf(
"linear" to makeDateLineChartData(x, y, lineChartFormat.timeAccuracy)
)
//② ~ ⑦ Graph creation
setupLineChart(allLinesEntries, findViewById(R.id.lineChartExample), lineChartFormat, lineDataSetFormat, context)
[As mentioned above](https://qiita.com/c60evaporator/items/b8f8c83dd3630c0091cf#%E9%9D%9E%E7%AD%89%E9%96%93%E9%9A%94%E3%81% AA% E6% 99% 82% E9% 96% 93% E3% 82% 92% E6% AD% A3% E7% A2% BA% E3% 81% AB% E8% A1% A8% E7% 8F% BE% E3% 81% 97% E3% 81% 9F% E3% 81% 84% E3% 81% A8% E3% 81% 8D), because the above method plots the data points in the X direction at equal intervals. If the data acquisition interval is not constant, the time will not be represented accurately on the horizontal axis.
If you want to express the time accurately in such a case, use Chart format. timeAccuracy = true Specify.
//Chart format
var lineChartFormat = LineChartFormat(
timeAccuracy = true,
/*Specify other Chart formats here*/
)
The difference from the time of one is -Specify the DataSet format for the number of lines ・ Data is stored in Entry for the number of lines It will be.
//Creation of sample data for display//
val x = listOf<Float>(1f, 2f, 3f, 5f, 8f, 13f, 21f, 34f)//X-axis data
val y1 = x.map{it}//Y-axis data 1 (X-axis squared)
val y2 = x.map{it*it}//Y-axis data 2 (X-axis squared)
//Chart format
var lineChartFormat = LineChartFormat(/*Chart format specification here*/)
//DataSet format(Category name Map)
var lineDataSetFormat = mapOf(
"linear" to LineDataSetFormat(/*Specify DataSet format here*/),
"square" to LineDataSetFormat(/*Specify DataSet format here*/)
)
//① Data storage in Entry(Category name Map)
val allLinesEntries: MutableMap<String, MutableList<Entry>> = mutableMapOf(
"linear" to makeLineChartData(x, y1),
"square" to makeLineChartData(x, y2)
)
//② ~ ⑦ Graph creation
setupLineChart(allLinesEntries, lineChart, lineChartFormat, lineDataSetFormat, context)
If you set the method for storing data to makeDateLineChartData, you can create a graph with multiple lines and time series.
The implementation method of the bar graph is explained separately for the layout (.xml) and the processing part (.kt).
As with LineChart, embed the widget for BarChart in the layout (eg activity_main.xml).
activity_main.xml
:
<com.github.mikephil.charting.charts.BarChart
android:id="@+id/barChartExample"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
:
Implement the process of calling the bar chart creation method in your Kotlin file (eg MainActivity.kt). ・ When there is only one stick ・ When you want to make the horizontal axis time series ・ When displaying multiple bars in a stacked manner ・ When displaying multiple bars side by side I will explain each example separately.
It is almost the same as the line graph. I think you can just change the class name named "Line ~" to "Bar ~".
//Creation of sample data for display//
val x = listOf<Float>(1f, 2f, 3f, 4f, 6f, 7f, 8f, 9f)//X-axis data
val y = x.map{it*it}//Y-axis data (X-axis squared)
//Chart format
var barChartFormat = BarChartFormat(/*Chart format specification here*/)
//DataSet format(Category name Map)
var barDataSetFormat = mapOf(
"square" to BarDataSetFormat(/*Specify DataSet format here*/)
)
//① Data storage in Entry(Category name Map)
val allBarsEntries: MutableMap<String, MutableList<BarEntry>> = mutableMapOf(
"square" to makeBarChartData(x, y)
)
//② ~ ⑦ Graph creation
setupBarChart(allBarsEntries, barChart, barChartFormat, barDataSetFormat, context)
If you want to make the horizontal axis time series, use the method to store data in Entry. makeBarChartData() → makeDateBarChartData() Change to
//Creation of sample data for display//
//X-axis data(time)
val sdf: SimpleDateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
val x = listOf<Date>(
sdf.parse("2020/09/01 00:00:00"),
sdf.parse("2020/09/01 06:00:00"),
sdf.parse("2020/09/01 12:00:00"),
sdf.parse("2020/09/01 18:00:00"),
sdf.parse("2020/09/02 00:00:00"),
sdf.parse("2020/09/02 06:00:00"),
sdf.parse("2020/09/02 12:00:00"),
sdf.parse("2020/09/03 18:00:00"),
)
val y = listOf<Float>(1f, 2f, 3f, 5f, 8f, 13f, 21f, 34f)//Y-axis data(Numerical value)
//Chart format
var barChartFormat = BarChartFormat(/*Chart format specification here*/)
//DataSet format(Category name Map)
var barDataSetFormat = mapOf(
"square" to BarDataSetFormat(/*Specify DataSet format here*/)
)
//① Data storage in Entry(Category name Map)
val allBarsEntries: MutableMap<String, MutableList<BarEntry>> = mutableMapOf(
"square" to makeDateBarChartData(x, y)
)
//② ~ ⑦ Graph creation
setupBarChart(allBarsEntries, barChart, barChartFormat, barDataSetFormat, context)
The difference from the time of one is
-The Y-axis data to be stored in Entry is the data that you want to accumulate in List <MutableList
//Creation of sample data for display//
val x = listOf<Float>(1f, 2f, 3f, 4f, 6f, 7f, 8f, 9f)//X-axis data
val y = x.map{ mutableListOf(it, it*it)}//Y-axis data (1 item):X-axis 1st power, 2 items:X squared)
//Chart format
var barChartFormat = BarChartFormat(/*Chart format specification here*/)
//DataSet format(Category name Map)
var barDataSetFormat = mapOf(
"stack" to BarDataSetFormat(
stackLabels = listOf("linear","square"),
/*Specify other DataSet formats here*/
)
)
//① Data storage in Entry(Category name Map)
val allBarsEntries: MutableMap<String, MutableList<BarEntry>> = mutableMapOf(
"stack" to makeStackBarChartData(x, y)
)
//② ~ ⑦ Graph creation
setupBarChart(allBarsEntries, barChart, barChartFormat, barDataSetFormat, context)
As with multiple polygonal lines, the difference from one line is -Specify the DataSet format for the number of bars ・ Data is stored in Entry for the number of bars It will be. ** * Please note that it can be used only when the horizontal axis spacing is constant **
//Creation of sample data for display
val x = listOf<Float>(1f, 2f, 3f, 4f, 5f, 6f, 7f, 8f)//X-axis data
val y1 = x.map{it}//Y-axis data 1 (X-axis squared)
val y2 = x.map{it*it}//Y-axis data 2 (X-axis squared)
//Chart format
var barChartFormat = BarChartFormat(/*Chart format specification here*/)
//DataSet format(Category name Map)
var barDataSetFormat = mapOf(
"linear" to BarDataSetFormat(/*Specify DataSet format here*/),
"square" to BarDataSetFormat(/*Specify DataSet format here*/)
)
//① Data storage in Entry(Category name Map)
val allBarsEntries: MutableMap<String, MutableList<BarEntry>> = mutableMapOf(
"linear" to makeBarChartData(x, y1),
"square" to makeBarChartData(x, y2)
)
//② ~ ⑦ Graph creation
setupBarChart(allBarsEntries, barChart, barChartFormat, barDataSetFormat, context)
"Candlestick graph" is a graph used in stock price charts. Can also be used as a substitute for box plots
The implementation method is explained separately for the layout (.xml) and the processing section (.kt).
As with LineChart, embed the widget for CandleStickChart in the layout (eg activity_main.xml).
activity_main.xml
:
<com.github.mikephil.charting.charts.CandleStickChart
android:id="@+id/candleStickChartExample"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
:
Implement the process of calling the candlestick graph creation method in the Kotlin file (eg MainActivity.kt). ・ When the horizontal axis is a numerical value ・ When you want to make the horizontal axis time series I will explain each example separately.
Note that when storing data in the Entry, you need to specify five types of arguments: X-axis value, Y maximum value, Y minimum value, Y start value, and Y end value.
//Creation of sample data for display//
val x = listOf<Float>(2f, 3f, 4f, 5f, 6f, 7f, 8f, 9f)//X-axis data
val yHigh = x.map{it * 2}//Y-axis data (maximum value)
val yLow = x.map{it}//Y-axis data (minimum value)
val yOpen = x.map{it + 1}//Y-axis data (starting value)
val yClose = x.map{it + 2}//Y-axis data (end value)
//Chart format
var candleChartFormat = CandleChartFormat(/*Chart format specification here*/)
//DataSet format(Category name Map)
var candleDataSetFormat = CandleDataSetFormat(/*Specify DataSet format here*/)
//① Data storage in Entry(Category name Map)
val candleEntries = makeCandleChartData(x, yHigh, yLow, yOpen, yClose)
//② ~ ⑦ Graph creation
setupCandleStickChart(candleEntries, candleStickChart, candleChartFormat, candleDataSetFormat, context)
If you want to make the horizontal axis time series, use the method to store data in Entry. makeCandleChartData() → makeDateCandleChartData() Change to
//Creation of sample data for display//
//X-axis data(time)
val sdf: SimpleDateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
val x = listOf<Date>(
sdf.parse("2020/09/01 00:00:00"),
sdf.parse("2020/09/01 06:00:00"),
sdf.parse("2020/09/01 12:00:00"),
sdf.parse("2020/09/01 18:00:00"),
sdf.parse("2020/09/02 00:00:00"),
sdf.parse("2020/09/02 06:00:00"),
sdf.parse("2020/09/02 12:00:00"),
sdf.parse("2020/09/03 18:00:00"),
)
val ySeed = listOf<Float>(2f, 3f, 4f, 5f, 6f, 7f, 8f, 9f)//For Y-axis data generation
val yHigh = ySeed.map{it * 2}//Y-axis data (maximum value)
val yLow = ySeed.map{it}//Y-axis data (minimum value)
val yOpen = ySeed.map{it + 1}//Y-axis data (starting value)
val yClose = ySeed.map{it + 2}//Y-axis data (end value)
//Chart format
var candleChartFormat = CandleChartFormat(/*Chart format specification here*/)
//DataSet format
var candleDataSetFormat = CandleDataSetFormat(/*Specify DataSet format here*/)
//① Data storage in Entry
val candleEntries = makeDateCandleChartData(x, yHigh, yLow, yOpen, yClose)
//② ~ ⑦ Graph creation
setupCandleStickChart(candleEntries, candleStickChart, candleChartFormat, candleDataSetFormat, context)
The implementation method of the pie chart is explained separately for the layout (.xml) and the processing part (.kt or .java).
As with LineChart, embed the widget for PieChart in the layout (eg activity_main.xml).
activity_main.xml
:
<com.github.mikephil.charting.charts.PieChart
android:id="@+id/pieChartExample"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
:
Implement the process of calling the pie chart creation method in your Kotlin file (eg MainActivity.kt).
//Creation of sample data for display//
val dimensions = listOf("A", "B", "C", "D")//Name of the split circle(String type)
val values = listOf(1f, 2f, 3f, 4f)//The size of the dividing circle(Float type)
//Chart format
var pieChartFormat = PieChartFormat(/*Chart format specification here*/)
//DataSet format
var pieDataSetFormat = PieDataSetFormat(/*Specify DataSet format here*/)
//① Data storage in Entry
val pieEntries = makePieChartEntries(dimensions, values)
//② ~ ⑦ Graph creation
setupPieChart(pieEntries, pieChart, "PieChart", pieChartFormat, pieDataSetFormat)
I will explain what is applied to the entire graph (Chart) and what is applied to each category (DataSet) separately.
As for the application method, each property content can be specified by giving an argument to the constructor as shown below. (If not specified, [Previous Chapter "Usage"](https://qiita.com/c60evaporator/items/b8f8c83dd3630c0091cf#%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3 The UI will be as shown in% 95))
//Creation of sample data for display//
//X-axis data(time)
val sdf: SimpleDateFormat = SimpleDateFormat("yyyy/M")
val x = listOf<Date>(
sdf.parse("1990/1"),
sdf.parse("1995/1"),
sdf.parse("2000/1"),
sdf.parse("2005/1"),
sdf.parse("2010/1"),
sdf.parse("2015/1"),
sdf.parse("2018/1")
)
val y1 = listOf(6.0f, 7.6f, 10.3f, 13.0f, 15.0f, 18.2f, 20.6f)//Y-axis data 1 (USA)
val y2 = listOf(0.4f, 0.7f, 1.2f, 2.3f, 6.1f, 11.2f, 13.4f)//Y-axis data 2 (China)
val y3 = listOf(3.1f, 5.4f, 4.8f, 4.8f, 5.7f, 4.4f, 5.0f)//Y-axis data 3 (Japan)
val y4 = listOf(1.6f, 2.6f, 1.9f, 2.8f, 3.4f, 3.4f, 4.0f)//Y-axis data 4 (Germany)
///////////Specify Chart format here///////////
var lineChartFormat = LineChartFormat(
legendTextSize = 10f,
description = "Changes in GDP of major countries",
descriptionTextSize = 15f,
descriptionYOffset = -10f,
bgColor = Color.DKGRAY,
xAxisDateFormat = SimpleDateFormat("yyyy year"),
toolTipDateFormat = SimpleDateFormat("yyyy year"),
toolTipDirection = "xy",
toolTipUnitY = "Trillion dollars"
)
///////////Specify the DataSet format here(Category name Map)///////////
var lineDataSetFormat = mapOf(
"America" to LineDataSetFormat(//Specify DataSet format for line 1
lineColor = UNIVERSAL_BLUE,
lineWidth = 2f
),
"China" to LineDataSetFormat(//Specify the DataSet format for line 2
lineColor = UNIVERSAL_RED,
lineWidth = 2f
),
"Japan" to LineDataSetFormat(//Line 3 DataSet format specification
lineColor = UNIVERSAL_SKYBLUE,
lineWidth = 2f
),
"Germany" to LineDataSetFormat(//Line 4 DataSet format specification
lineColor = Color.LTGRAY,
lineWidth = 2f
)
)
//① Data storage in Entry(Category name Map)
val allLinesEntries: MutableMap<String, MutableList<Entry>> = mutableMapOf(
"America" to makeDateLineChartData(x, y1, false),
"China" to makeDateLineChartData(x, y2, false),
"Japan" to makeDateLineChartData(x, y3, false),
"Germany" to makeDateLineChartData(x, y4, false)
)
//② ~ ⑦ Graph creation
setupLineChart(allLinesEntries, lineChart, lineChartFormat, lineDataSetFormat, context)
There are some implementation examples in GitHub MainActivity.kt ( Especially since the latter 4 methods), I think it will be easier to understand if you refer to this.
Below is a list of properties that can be specified in the Chart format.
** The link in the "Property name in MPAndroidChart" column ** illustrates how the UI actually changes (separate article).
Applicable target | Items to change | Property name in Chart format | Type | Remarks | Property name in MPAndroidChart | Line | bar graph | Candlestick | pie chart |
---|---|---|---|---|---|---|---|---|---|
Usage Guide | Mark shape | legendFormat | Legend.LegendForm? | nullならUsage Guide表示なし | .legend.form | 〇 | 〇 | 〇 | 〇 |
Usage Guide | Letter color | legentTextColor | Int? | Default if null(black) | .legend.textColor | 〇 | 〇 | 〇 | 〇 |
Usage Guide | font size | legendTextSize | Float? | Default if null | .legend.textSize | 〇 | 〇 | 〇 | 〇 |
Description label | Display string | description | String? | nullならDescription labelなし | .description.text | 〇 | 〇 | 〇 | 〇 |
Description label | Letter color | descriptionTextColor | Int? | Default if null(black) | .description.textColor | 〇 | 〇 | 〇 | 〇 |
Description label | font size | descriptionTextSize | Float? | Default if null | .description.textSize | 〇 | 〇 | 〇 | 〇 |
Description label | Horizontal position fine adjustment | descriptionXOffset | Float? | Default if null | .description.xOffset | 〇 | 〇 | 〇 | 〇 |
Description label | Vertical position fine adjustment | descriptionYOffset | Float? | Default if null | .description.yOffset | 〇 | 〇 | 〇 | 〇 |
background | background色 | bgColor | Int? | Default if null(White) | .setBackgroundColor() | 〇 | 〇 | 〇 | 〇 |
Touch operation | Valid Invalid | touch | Boolean | .setTouchEnabled() | 〇 | 〇 | 〇 | ||
X-axis label | With or without display | xAxisEnabled | Boolean | .xAxis.isEnabled | 〇 | 〇 | 〇 | ||
X-axis label | Letter color | xAxisTextColor | Int? | Default if null(black) | .xAxis.textColor | 〇 | 〇 | 〇 | |
X-axis label | font size | xAxisTextSize | Float? | Default if null | .xAxis.textSize | 〇 | 〇 | 〇 | |
X-axis label | Time display format | xAxisDateFormat | SimpleDateFormat? | M if null/d H:mm | - | 〇 | 〇 | 〇 | |
Left Y-axis label | With or without display | yAxisLeftEnabled | Boolean | .axisLeft.isEnabled | 〇 | 〇 | 〇 | ||
Left Y-axis label | Letter color | yAxisLeftTextColor | Int? | Default if null(black) | .axisLeft.textColor | 〇 | 〇 | 〇 | |
Left Y-axis label | font size | yAxisLeftTextSize | Float? | Default if null | .axisLeft.textSize | 〇 | 〇 | 〇 | |
Left Y-axis label | Display lower limit | yAxisLeftMin | Float? | If null, there is no lower limit | .axisLeft.axisMinimum | 〇 | 〇 | 〇 | |
Left Y-axis label | Display upper limit | yAxisLeftMax | Float? | No upper limit if null | .axisLeft.axisMaximam | 〇 | 〇 | 〇 | |
Right Y-axis label | With or without display | yAxisRightEnabled | Boolean | .axisRight.isEnabled | 〇 | 〇 | 〇 | ||
Right Y-axis label | Letter color | yAxisRightTextColor | Int? | Default if null(black) | .axisRight.textColor | 〇 | 〇 | 〇 | |
Right Y-axis label | font size | yAxisRightTextSize | Float? | Default if null | .axisRight.textSize | 〇 | 〇 | 〇 | |
Right Y-axis label | Display lower limit | yAxisRightMin | Float? | If null, there is no lower limit | .axisRight.axisMinimum | 〇 | 〇 | 〇 | |
Right Y-axis label | Display upper limit | yAxisRightMax | Float? | No upper limit if null | .axisRight.axisMaximam | 〇 | 〇 | 〇 | |
Enlargement operation | Expansion direction | zoomDirection | String? | "x", "y", "xy" If null, expansion is invalid |
.isScaleXEnabled .isScaleYEnabled .setScaleEnabled() |
〇 | 〇 | 〇 | |
Enlargement operation | Pinch operation effective | zoomPinch | Boolean | .setPinchZoom() | 〇 | 〇 | 〇 | ||
Tooltip | Axis to display | toolTipDirection | String? | "x", "y", "xy" nullならTooltipなし |
.marker | 〇 | 〇 | 〇 | |
Tooltip | Format for time series graphs | toolTipDateFormat | SimpleDateFormat? | M if null/d H:mm | .marker | 〇 | 〇 | 〇 | |
Tooltip | X-axis unit | toolTipUnitX | String | The default is no unit("") | .marker | 〇 | 〇 | 〇 | |
Tooltip | Y-axis unit | toolTipUnitY | String | The default is no unit("") | .marker | 〇 | 〇 | 〇 | |
X-axis display method | Time axis scale accuracy | timeAccuracy | Boolean | If True, the time axis is displayed accurately(Labels are maximum and minimum only) | - | 〇 | |||
label | Letter color | labelColor | Int? | Default if null(black) | .setEntryLabelColor() | 〇 | |||
label | font size | labelTextSize | Float? | Default if null | .setEntryLabelTextSize() | 〇 | |||
Central text | Display string | centerText | String? | No central text if null | .centerText | 〇 | |||
Central text | Letter color | centerTextColor | Int? | Default if null(black) | .setCenterTextColor() | 〇 | |||
Central text | font size | centerTextSize | Float? | Default if null | .setCenterTextSize() | 〇 | |||
Central hole | Hole radius | holeRadius | Float? | Default if null | .holeRadius | 〇 | |||
Central hole | Width of light-colored area around the hole | transparentCircleRadius | Float? | Default if null | .transparentCircleRadius | 〇 | |||
Central hole | Hole fill color | holeColor | Int? | Default if null(black) | .setHoleColor() | 〇 | |||
______________ | ____________ | ________________ |
xAxisDateFormat Change the X-axis time display format (only for time series graphs, default is "M / d H: mm")
var lineChartFormat = LineChartFormat(xAxisDateFormat = SimpleDateFormat("d day H o'clock"))
timeAccuracy [Same as above](https://qiita.com/c60evaporator/items/b8f8c83dd3630c0091cf#%E9%9D%9E%E7%AD%89%E9%96%93%E9%9A%94%E3% 81% AA% E6% 99% 82% E9% 96% 93% E3% 82% 92% E6% AD% A3% E7% A2% BA% E3% 81% AB% E8% A1% A8% E7% 8F% BE% E3% 81% 97% E3% 81% 9F% E3% 81% 84% E3% 81% A8% E3% 81% 8D), specifies the accuracy of the timeline scale (time series line graph only)
Accurately display scale, time label only display maximum and minimum
var lineChartFormat = LineChartFormat(timeAccuracy=true)
Shows all time labels, less accurate
var lineChartFormat = LineChartFormat(timeAccuracy=false)
toolTipDirection
No tooltip display
var lineChartFormat = LineChartFormat(toolTipDirection=null)
Show X-axis values in tooltips
var lineChartFormat = LineChartFormat(toolTipDirection="x")
Show Y-axis values in tooltips
var lineChartFormat = LineChartFormat(toolTipDirection="y")
Show both X-axis and Y-axis values in tooltips
var lineChartFormat = LineChartFormat(toolTipDirection="xy")
toolTipDateFormat Change the time display format of the tooltip (only for time series graphs, default is "M / d H: mm")
Tooltip time display format"d day H o'clock"To
var lineChartFormat = LineChartFormat(
toolTipDirection="xy",
toolTipDateFormat = SimpleDateFormat("d day H o'clock")
)
toolTipUnitX Specifies the unit to add to the X-axis display of the tooltip (default is no unit)
Tooltip X-axis units"Day"To
var lineChartFormat = LineChartFormat(
toolTipDirection="xy",
toolTipUnitX = "Day"
)
toolTipUnitY Specifies the unit to add to the Y-axis display of the tooltip (default is no unit)
Tooltip Y-axis unit"Circle"To
var lineChartFormat = LineChartFormat(
toolTipDirection="xy",
toolTipUnitY = "Circle"
)
Below is a list of properties that can be specified in the DataSet format (specified for each line, each bar, etc.).
** The link in the "Property name in MPAndroidChart" column ** illustrates how the UI actually changes (separate article).
Applicable target | Items to change | Property name in DataSet format | Type | Remarks | Property name in MPAndroidChart | Line | bar graph | Candlestick | pie chart |
---|---|---|---|---|---|---|---|---|---|
Value display | Value displayの有無 | drawValue | Boolean | .setDrawValues() | 〇 | 〇 | 〇 | 〇 | |
Value display | Value displayの文字色 | valueTextColor | Int? | Default if null(black) | .valueTextColor | 〇 | 〇 | 〇 | 〇 |
Value display | Value displayの文字サイズ | valueTextSize | Float? | Default if null | .valueTextSize | 〇 | 〇 | 〇 | 〇 |
Value display | Value displayのフォーマット | valueTextFormatter | String? | Default if null | .valueFormatter | 〇 | 〇 | 〇 | 〇 |
axis | 左右axisどちらを使用するか | axisDependency | YAxis.AxisDependency? | nullなら左Yaxis | .axisDependency | 〇 | 〇 | ||
line | lineの色 | lineColor | Int? | Default if null(light blue) | .color | 〇 | |||
line | width | lineWidth | Float? | Default if null | .lineWidth | 〇 | |||
line | Complementary method | fittingMode | LineDataSet.Mode? | Default if null(直line補完) | .mode | 〇 | |||
Data point | With or without display | drawCircles | Boolean | .setDrawCircles() | 〇 | ||||
Data point | Frame color | circleColor | Int? | Default if null(light blue) | .setCircleColor() | 〇 | |||
Data point | Frame radius | circleRadius | Float? | Default if null | .circleRadius | 〇 | |||
Data point | Hole fill color | circleHoleColor | Int? | Default if null(White) | .circleHoleRadius | 〇 | |||
Data point | Hole radius | circleHoleRadius | Float? | Default if null | .circleHoleColor | 〇 | |||
rod | rodの色 | barColor | Int? | Default if null(light blue) | .color | Other than stacking | |||
rod | 各Stackrodの色リスト | barColors | List |
.colors | Stack | ||||
rod | Stackrodのカテゴリ名 | stackLabels | List |
Default if null(Fill with label name) | .stackLabels | Stack | |||
Candle thin line | Line color | shadowColor | Int | .shadowColor | 〇 | ||||
Candle thin line | width | shadowWidth | Float? | Default if null | .shadowWidth | 〇 | |||
Thick candle line | Color when decreasing | decreasingColor | Int | .decreasingColor | 〇 | ||||
Thick candle line | Fill format when decreasing | decreasingPaint | Paint.Style? | If null, there is a fill | .decreasingPaintStyle | 〇 | |||
Thick candle line | Color when increasing | increasingColor | Int? | No color if null | .increasingColor | 〇 | |||
Thick candle line | Fill format when increasing | increasingPaint | Paint.Style? | If null, no fill | .increasingPaintStyle | 〇 | |||
Divided circle | Divided circleの色 | colors | List |
.colors | 〇 | ||||
______________ | ____________ | ________________ |
valueTextFormatter Specifies the format of the value display (In MPAndroidChart, specify by overriding in ValueFormatter class, but in this package, specify by String type)
integer(0th place after the decimal point)Display with
var lineDataSetFormat = mapOf(
"linear" to LineDataSetFormat(
drawValue = true,
valueTextSize = 12f,
valueTextFormatter = "%.0f"
)
)
Displayed in 2 decimal places
var lineDataSetFormat = mapOf(
"linear" to LineDataSetFormat(
drawValue = true,
valueTextSize = 12f,
valueTextFormatter = "%.2f"
)
)
1st place after the decimal point +"Circle"Display with
var lineDataSetFormat = mapOf(
"linear" to LineDataSetFormat(
drawValue = true,
valueTextSize = 12f,
valueTextFormatter = "%.1f yen"
)
)
For graphs that are not time series (X-axis is a Float type number)
val x = listOf<Float>(1f, 2f, 3f, 5f, 8f, 13f, 21f, 34f)
val y = x.map{it*it}
var entryList = mutableListOf<Entry>()
for(i in x.indices){
entryList.add(Entry(x[i], y[i]))
}
If you enter the X-axis value in the first term of Entry and the Y-axis value in the second term, it will match the input X-axis value.
val lineDataSets = ListOf<ILineDataSet>(LineDataSet())
lineChart.data = LineData(lineDataSets)
If so, both axes will be plotted correctly as shown in the figure below.
When the X-axis is a Date (java.util.Date) type number, the X-axis value cannot be entered in the first term of Entry.
val sdf: SimpleDateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
val x = listOf<Date>(
sdf.parse("2020/09/01 00:00:00"),
sdf.parse("2020/09/01 06:00:00"),
sdf.parse("2020/09/01 12:00:00"),
sdf.parse("2020/09/01 18:00:00"),
sdf.parse("2020/09/02 00:00:00"),
sdf.parse("2020/09/02 06:00:00"),
sdf.parse("2020/09/02 12:00:00"),
sdf.parse("2020/09/02 18:00:00"),
)
val y = listOf<Float>(1f, 2f, 3f, 5f, 8f, 13f, 21f, 34f)
//Data storage in Entry
var entryList = mutableListOf<Entry>()
for(i in x.indices){
entryList.add(
Entry(x[i], y[i])//← I get an error here
)
}
val lineDataSets = listOf<ILineDataSet>(LineDataSet(entryList,"label"))
lineChart.data = LineData(lineDataSets)
Since it is necessary to store the Float type in the first term of Entry, convert the index to the Float type and store it (instead, store the date data in the third term).
:
//Data storage in Entry
var entryList = mutableListOf<Entry>()
for(i in x.indices){
entryList.add(
Entry(i.toFloat(), y[i], x[i])
)
}
:
But as it is !
Like, the X-axis label is just an index and I don't know what time it is. You can display the label by converting the time to a string list and specifying it as the X-axis label, as shown below.
:
//Convert X-axis value from date type to character string and specify it as X-axis label
val xStr = x.map { SimpleDateFormat("M/d H:mm").format(it)}
lineChart.xAxis.valueFormatter = IndexAxisValueFormatter(xStr)
val lineDataSets = listOf<ILineDataSet>(LineDataSet(entryList,"label"))
lineChart.data = LineData(lineDataSets)
Recommended Posts