B4A Library MPAndroidCharts - Various type of graphs / charts (Latest library V1.22 in post #1)

Edit 6 Sep 2015: Post #3 adds Single Vertical Bar Charts and update for Pie Charts
Edit 8 Sep 2015 Post #6 update for Single Vertical Bar Charts
Edit 11 Sep 2015 Post #7 adds Single Line Charts
Edit 12 Sep 2015 Post #8 update for Single Line Charts
Edit 12 Sep 2015 Post #9 adds Single Horizontal Bar Charts
Edit 12 Sep 2015 Post #11 adds Radar Charts
Edit 13 Sep 2015 Post #12 update for Single Line and Single Bar Charts
Edit 14 Sep 2015 Post #16 update for Radar Charts
Edit 16 Sep 2015 Post #19 adds Multiple Line Charts
Edit 17 Sep2016 Post #21 adds Multi Vertical Bar Charts
Edit 19 Sep 2015 Post #23 adds Multi Bubble Charts
Edit 19 Sep 2015 Post #24 adds Multi Horizontal Bar Charts
Edit 19 Sep 2015 Post #25 adds Multi Scatter Charts
Edit 19 Sep 2015 Post #26 adds Stacked Bar Charts
Edit 20 Sep 2015 Post #27 adds Candlestick Charts
Edit 20 Sep 2015 Post #28 adds Combined Line & Bar Charts
Edit 23 Sep 2015 Post #31 fixed no-show of Chart Title for Combined Charts and added ability to rotate X-axis labels between -30 and + 30 degrees

I am busy wrapping this Github project. Attached is the Pie Chart functionality of the project/library. Posting the B4A project and Library files. Copy the library files to your additional library folder.

Some remarks about the Pie Chart:
1. It will display the values passed as a percentage of the total of the values that you pass
2. There are 3 x arrays that are passed to the library. Ensure that you pass the same number of elements in each of the arrays.
3. When you click on a pie slice the slice will increase in radial size (see pics below)
4. If you click on the radial increased slice it will return to normal size.
5. You can spin the pie chart around its centre point (CW and ACW) with your finger.

Untouched ...

Pie.gif


1.png


Green slice touched ...

2.png


Pie Chart rotated with finger...

3.png



Some sample code:

B4X:
#Region  Project Attributes
    #ApplicationLabel: MPChart
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: landscape
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

    Private mpc1 As PieChart
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("main")

mpc1.DrawHoleEnabled = True
mpc1.HoleColorTransparent = True

mpc1.TransparentCircleColor = Colors.White
mpc1.TransparentCircleAlpha = 110

mpc1.HoleRadius = 58.0
mpc1.TransparentCircleRadius = 61.0

mpc1.DrawCenterText = True

mpc1.CenterText = "Wrapped by Johan"
mpc1.CenterTextColor = Colors.White
mpc1.CenterTextRadiusPercent = 100.0
mpc1.CenterTextSize = 15.0

mpc1.DrawSliceText = True
mpc1.HoleColor = Colors.Black
mpc1.TransparentCircleColor = Colors.Transparent

mpc1.setTheLegendPosition
mpc1.TheLegendColor = Colors.yellow
mpc1.TheLegendTextSize = 12.0
mpc1.LegendTitle = "MONTHS"

mpc1.ChartDescription = "TITLE : Some Arbitrary Data"
mpc1.ChartDescriptionColor = Colors.ARGB(200,0,255,255)
mpc1.ChartDescriptionTextSize = 17

mpc1.ValueTextColor = Colors.Black
mpc1.ValueTextSize = 15.0

mpc1.PieColors = Array As Int(Colors.Blue, Colors.Yellow, Colors.Green, Colors.Red, Colors.Magenta, Colors.Cyan)
mpc1.LegendText = Array As String("Jan", "Feb", "Mar", "Apr", "May", "Jun")
mpc1.ChartData = Array As Float(128.0, 16.0, 46.0, 40.0, 30.0, 40.0)    'values - it will be converted to %

mpc1.PieData = 6

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub
 

Attachments

  • b4aMPChart.zip
    7.9 KB · Views: 1,408
  • mpChartLibraryFiles.zip
    221.5 KB · Views: 1,494
  • mpChartLibV1.15.zip
    355.2 KB · Views: 608
  • mpChartLibV1.16.zip
    355.7 KB · Views: 607
  • mpChartLibV1.17.zip
    355.8 KB · Views: 775
  • mpChartLibV1.18.zip
    356.4 KB · Views: 685
  • mpChartLibV1.20.zip
    358.1 KB · Views: 467
  • mpChartLibV1.21.zip
    358 KB · Views: 41
  • mpChartLibV1.22.zip
    359.2 KB · Views: 66
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
Hello to all
I'm trying to use the MPStackedBarChart example with the version 1.07 library, but when I click on the blocks the system goes wrong.

See the error

B4X:
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean anywheresoftware.b4a.BA.subExists(java.lang.String)' on a null object reference
    at com.github.mikephil.charting.charts.BarLineChartBase.getMarkerPosition(BarLineChartBase.java:560)
    at com.github.mikephil.charting.charts.Chart.drawMarkers(Chart.java:603)
    at com.github.mikephil.charting.charts.BarLineChartBase.onDraw(BarLineChartBase.java:259)
    at android.view.View.draw(View.java:16263)
    at android.view.View.updateDisplayListIfDirty(View.java:15186)
    at android.view.View.getDisplayList(View.java:15209)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3692)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3671)
    at android.view.View.updateDisplayListIfDirty(View.java:15146)
    at android.view.View.getDisplayList(View.java:15209)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3692)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3671)
    at android.view.View.updateDisplayListIfDirty(View.java:15146)
    at android.view.View.getDisplayList(View.java:15209)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3692)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3671)
    at android.view.View.updateDisplayListIfDirty(View.java:15146)
    at android.view.View.getDisplayList(View.java:15209)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3692)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3671)
    at android.view.View.updateDisplayListIfDirty(View.java:15146)
    at android.view.View.getDisplayList(View.java:15209)
    at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:307)
    at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:313)
    at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:352)
    at android.view.ViewRootImpl.draw(ViewRootImpl.java:2818)
    at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2638)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2226)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1230)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6748)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:777)
    at android.view.Choreographer.doCallbacks(Choreographer.java:590)
    at android.view.Choreographer.doFrame(Choreographer.java:560)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:763)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:6134)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

thanks

I would suggest that for now you use V1.06 (attached). I need to revisit V1.07 as I discovered an error in V1.07 that I need to rethink and correct.....
 

Attachments

  • mpChartLib.xml
    377.5 KB · Views: 167
  • mpChartLib.jar
    363.7 KB · Views: 194

Pencil3

Member
Licensed User
Have a question that I have not been able to figure out on my own. I am trying to use your single line chart to plot points from a db. Have that working almost perfectly, I would like to plot the last 7 entries from the db. When using LineData = 7 the first 7 entries from the db are plotted. How can I set it to plot the last 7 entries?
 

Descartex

Well-Known Member
Licensed User
Longtime User
Have a question that I have not been able to figure out on my own. I am trying to use your single line chart to plot points from a db. Have that working almost perfectly, I would like to plot the last 7 entries from the db. When using LineData = 7 the first 7 entries from the db are plotted. How can I set it to plot the last 7 entries?
I think it is not a problem of the library, but of the data that you pass to the chart.
Try to pass only the last 7 data in your database and will surely display correctly as you want.
Regards.
 

Pencil3

Member
Licensed User
Thank you! Very much appreciate the help. You have put me on the right track. I just need to flip the points on the graph now so that the last entry shows on the right side of the graph and first entry on the left side. The graph currently shows the opposite.

SELECT * FROM DATAS ORDER BY ID DESC LIMIT 7;
 

Pencil3

Member
Licensed User
Thanks again jahswani for pointing me in the right direction.

"SELECT * FROM (SELECT * FROM db DATAS ORDER BY ID DESC LIMIT 7) TMP ORDER BY ID ASC"

Thank you! Very much appreciate the help. You have put me on the right track. I just need to flip the points on the graph now so that the last entry shows on the right side of the graph and first entry on the left side. The graph currently shows the opposite.
 

Pencil3

Member
Licensed User
I may be missing something as far as rounding goes. If I try to plot the value "38.5" the graph displays it as "38.00". Another example would be trying to plot the value "9.5". On the graph it shows as "9.0". What am I overlooking?
 

Pencil3

Member
Licensed User
Yes, I did, but it didn't help. For example when I set mlc1.GraphValueDigits = Array As Int(2, 2, 2, 2, 2) and plot the value of "38.5" the value is plotted on the graph as 38.0.

Have you tried setting the GraphValueDigits property?
 

beaker

Member
Licensed User
Yes, I did, but it didn't help. For example when I set mlc1.GraphValueDigits = Array As Int(2, 2, 2, 2, 2) and plot the value of "38.5" the value is plotted on the graph as 38.0.
Hmmm... I thought that would fix your problem. Without seeing the code it's difficult to say. Your values aren't being converted to integers somewhere along the line are they?
 

Johan Schoeman

Expert
Licensed User
Longtime User
Yes, I did, but it didn't help. For example when I set mlc1.GraphValueDigits = Array As Int(2, 2, 2, 2, 2) and plot the value of "38.5" the value is plotted on the graph as 38.0.
Can you upload a small sample project? Will be easier to see what the problem is.
 

Pencil3

Member
Licensed User
Beaker is correct, they are being converted. Trying to figure it out lol.

B4X:
Dim SalValue As List :SalValue.Initialize
            Dim SalDate As List    :SalDate.Initialize
            Dim txtSal As String
            Dim CursorSal As Cursor
                       
            txtSal="SELECT * FROM (SELECT * FROM db DATAS ORDER BY ID DESC LIMIT 14) TMP ORDER BY ID ASC"
            CursorSal=Starter.SQL1.ExecQuery(txtSal)
            For i=0 To CursorSal.RowCount -1
                CursorSal.Position=i
                SalValue.Add(CursorSal.GetInt("A01Sal"))
                SalDate.Add(CursorSal.GetString("A01Date"))
            Next
           
            Dim PSal(SalValue.Size) As Float
            Dim CSal(SalDate.Size) As String
   
            For i=0 To SalValue.Size -1
                PSal(i)=SalValue.Get(i)
                CSal(i)=SalDate.Get(i)
            Next

Can you upload a small sample project? Will be easier to see what the problem is.
 

beaker

Member
Licensed User
Beaker is correct, they are being converted. Trying to figure it out lol.

B4X:
Dim SalValue As List :SalValue.Initialize
            Dim SalDate As List    :SalDate.Initialize
            Dim txtSal As String
            Dim CursorSal As Cursor
                     
            txtSal="SELECT * FROM (SELECT * FROM db DATAS ORDER BY ID DESC LIMIT 14) TMP ORDER BY ID ASC"
            CursorSal=Starter.SQL1.ExecQuery(txtSal)
            For i=0 To CursorSal.RowCount -1
                CursorSal.Position=i
                SalValue.Add(CursorSal.GetInt("A01Sal"))
                SalDate.Add(CursorSal.GetString("A01Date"))
            Next
         
            Dim PSal(SalValue.Size) As Float
            Dim CSal(SalDate.Size) As String
 
            For i=0 To SalValue.Size -1
                PSal(i)=SalValue.Get(i)
                CSal(i)=SalDate.Get(i)
            Next
Could it be this line that's causing the issue by any chance?
B4X:
SalValue.Add(CursorSal.GetInt("A01Sal"))

This might be better:
B4X:
SalValue.Add(CursorSal.GetDouble("A01Sal"))

or
B4X:
SalValue.Add(CursorSal.GetString("A01Sal"))

I've used GetString and assigned the value to a Float variable for the multiline chart. This worked for me.
 

Pencil3

Member
Licensed User
Success! Thank you beaker! Last night I tried:

B4X:
SalValue.Add(CursorSal.GetString("A01Sal"))

And I received empty string errors.

I just tried your second suggestion of:

B4X:
SalValue.Add(CursorSal.GetDouble("A01Sal"))

And presto, works perfectly. Thank you again.

Could it be this line that's causing the issue by any chance?
B4X:
SalValue.Add(CursorSal.GetInt("A01Sal"))

This might be better:
B4X:
SalValue.Add(CursorSal.GetDouble("A01Sal"))

or
B4X:
SalValue.Add(CursorSal.GetString("A01Sal"))

I've used GetString and assigned the value to a Float variable for the multiline chart. This worked for me.
 

beaker

Member
Licensed User
Success! Thank you beaker! Last night I tried:

B4X:
SalValue.Add(CursorSal.GetString("A01Sal"))

And I received empty string errors.

I just tried your second suggestion of:

B4X:
SalValue.Add(CursorSal.GetDouble("A01Sal"))

And presto, works perfectly. Thank you again.

Good, I'm pleased we found the issue. I think I've avoided the empty string issue by making sure the field(s) can't be empty either by validating the data before committing it to the DB Table and/or making sure the field's NotNull constraint is set to 'True'.

I think this has become off-topic for this thread now :oops:
 

peacemaker

Expert
Licensed User
Longtime User
HI, All

It's very interesting lib, trying the b4aMPMultiLineChartV5 sample.
But maybe any help, if it's possible: if we need to combine several lines on a single chart - the first line is the main one, making the max chart Y-size - the scale for whole the chart. And for the best data comparision at the same time - all next lines must be added within the scale of the first main line.
If main line values, say, are 600 ... 800 (Min1 ... Max1), but others are 0...5, or 0...100 - they must be scaled: * (Max1 - Min1) to fill the whole chart Y-size. But the visible values of the scaled lines should be shown real, without scaling.
Is it possible ?

See the screenshots:
1) the main line is red, the view should be as "0.28" (all lines maximally expanded by Y-axle)

2) green line value scaled is on "correctly scaled" = 379, but with value marker is needed as from "real values", really it's value = 50.

So, task is to show all lines maximally expanded by Y-axle, with real values on the markers.
 

Attachments

  • correctly scaled.png
    correctly scaled.png
    170.4 KB · Views: 189
  • real values.png
    real values.png
    166.6 KB · Views: 199
  • 0.28.png
    0.28.png
    177.7 KB · Views: 191
Last edited:

peacemaker

Expert
Licensed User
Longtime User
I mean in the prev post - it would be super, if to just add mlc1.Chart_x_Alias like mlc1.Chart_x_Data. And draw using _Data, but _Alias for showing on the marker.
This will allow to combine not only digit line charts, but any event lines.
 
Top