I want that my chart has two YAxis with different scales like the image . How I can change the scale for each axis?
Version 2.0.0-beta was released over the weekend with a CombinedChart, which allows plotting Line-, Bar-, Scatter- and CandleData in one chart. So the feature is finally available.
One note about what I found during my upgrade, you can't simply addDataSet() for each one, you have to generate the individual DataSet types (Bar, Line, Scatter, etc) and then use SetData() for the appropriate type, to trigger rendering.
Here is the example code.
The author of MPAndroidChart library clearly specifies here, (MPChart - Scatter Chart and LineChart in same plot), that this function is not yet available. So, I am also looking for a nicer approach.
As such, you can display two different chart types as one, still using this library, only by overlapping them.
I have done this on my side as it follows:
1. Edit the activity layout xml, having a FrameLayout as charts container.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
.......
<FrameLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:id="#+id/root_view">
</FrameLayout>
.......
</LinearLayout>
Now, in the Activity class, build the chart objects and attach them to the previous container:
// construct the charts, as different objects
// make sure to have valid Data Sets
LineChartItem lineChart = new LineChartItem(lineChartDataset, getApplicationContext());
BarChartItem barChart = new BarChartItem(barChartDataset, getApplicationContext());
// get the charts' container
FrameLayout frameLayout = (FrameLayout) findViewById(R.id.root_view);
// populate the container with the charts' views
frameLayout.addView(lineChart.getView(0, null, getApplicationContext()));
frameLayout.addView(barChart.getView(1, null, getApplicationContext()));
PROs/CONs for such a practice:
PROs
You have more combined charts with MPAndroidChart.
CONs
You need to take care of X and Y Labels alignment.
User Events: only the upper (in Z order) Chart View will get the user input, so you need to make sure that all the other chart views behave in the same manner (either processing OR ignoring the input, like zooming the chart or value selection).
I hope for a quick release of this great lib having this option. Thank you in advance Philipp Jahoda!
In my case, I'd every thing as suggested by the mpandroidcharts
Still I was getting same scale on "y axis right" and "y axis left"
the culprit was
combinedChart.axisLeft?.axisMinimum = //some calculations
combinedChart.axisLeft?.axisMaximum = //some calculations
combinedChart.axisRight?.axisMinimum = //some calculations
combinedChart.axisRight?.axisMaximum = //some calculations
Basically a copy paste error when you copy your perfect code from bar or line chart where setting the axis minimum and maximum where required.
Related
I am using the MPAndroidChart library to draw a pie chart in my app but if a value gets a little bit bigger than others all the other values and their labels get overlapped. I am also having some problems with labels in which some text gets clipped if it is a bit longer. I have seen apps(examples are given below) that adjust the size of the pie chart dynamically if they are provided with the same data scenario as I am having.
<com.github.mikephil.charting.charts.PieChart
android:id="#+id/main_dashboard_pie_chart"
android:layout_width="match_parent"
android:layout_height="400dp">
My Java code
pieDataSet.setColors(colors);
pieDataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
pieDataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
pieDataSet.setValueTextColor(Color.BLACK);
pieDataSet.setSliceSpace(2);
pieDataSet.setValueLinePart1OffsetPercentage(10); //starting of the line from center of the chart offset
pieDataSet.setValueLinePart1Length(0.6f);
pieDataSet.setValueLinePart2Length(0.5f);
PieData pieData = new PieData(pieDataSet);
pieData.setValueTextSize(13);
pieData.setValueFormatter(new PercentFormatter());
pieChart.setUsePercentValues(true);
pieChart.setData(pieData);
pieChart.setTransparentCircleRadius(45);
pieChart.setHoleRadius(40);
pieChart.setUsePercentValues(true);
pieChart.setCenterText("Expenses");
pieChart.setEntryLabelTextSize(10);
pieChart.animateY(1000, Easing.EasingOption.EaseInOutCubic);
pieChart.getDescription().setEnabled(false);
pieChart.setEntryLabelColor(Color.BLACK);
pieChart.setEntryLabelTextSize(13);
pieChart.setExtraBottomOffset(50f);
pieChart.setExtraTopOffset(50f);
pieChart.setExtraLeftOffset(50f);
pieChart.setExtraRightOffset(50f);
Legend l = pieChart.getLegend();
l.setDrawInside(false);
l.setEnabled(false);
Use This Library to solve the problem https://github.com/huzipiaopiao/MPAndroidChartFix
in XML Define your chart as shown below.
<com.teaanddogdog.mpandroidchartutil.PieChartFixCover
android:id="#+id/pie_chart"
android:layout_width="450dp"
android:layout_height="450dp"
app:mp_chart_out_value_place_mode="AVG"
app:mp_chart_auto_adapt_text_size="true"
/>
And you can access it in java code just as you access MPANdroidChart and can modify all the properties. Don't forget to upvote the question and answer if it helps you. All of the overlapping problems will be handled for you automatically. Thank you.
I'm using Android GraphView. I want to use DateAsXAxisLabelFormatter for x-axis, and a custom LabelFormatter for y-axis. Otherwise the y-axis labels gets cut off. See this: android graph-view y axis numbers being cut out
If I use static padding as suggested in the answers of above question, then there is extra padding sometimes.
See the images below:
When there are integers in y-labels (and I have given large padding to cope with numbers like: -0.0231, -0.0450, etc.):
When there are floating points in y-labels (and I have give small padding to make it look nice for numbers like: 10, 25, 40, etc):
And I'm unable to find the sweet spot.
If I could use a separate for both of the axes then I would set setMaximumFractionDigits(2), and provide a static padding. That remove my problem. But I couldn't do both, it seem to override the other (see the code for better understanding). I can either use DateAsXAxisLabelFormatter or a DefaultLabelFormatter but not both at the same time.
Here is the code:
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(2);
nf.setMaximumIntegerDigits(2);
graphView.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(MainActivity.this, simpleDateFormat));
graphView.getGridLabelRenderer().setLabelFormatter(new DefaultLabelFormatter(nf, nf)); // This overrides the previous LabelFormatter
// If I try to set them both together. I get this error.
graphView.getGridLabelRenderer().setLabelFormatter(new DateAsXAxisLabelFormatter(MainActivity.this, simpleDateFormat), nf);
//setLabelFormatter (LabelFormatter) in GridLabelRenderer cannot be applied to (DateAsXAxisLabelFormatter, java.text.NumberFormat)
How do I use both of the LabelFormatter separately for both axes?
I would like to add some extra labels to a LineChart (MPAndroidChart) like in the image below. Notice the "Advanced", "Novice" etc labels.
How could I add those to specified y-axis positions so they will always show up like y-axis labels but perhaps on the inside of the graph as shown - or on the right side if necessary?
Update:
All I needed to get what I needed was some LimitLines like this:
LimitLine noviceline = new LimitLine( SSGlobals.getWeightinPreferredUnits_fromPounds(standardweightsarr[2]) , getString(R.string.novice));
noviceline.setLineColor(ContextCompat.getColor(getActivity(), R.color.accentline));
noviceline.setTextColor(ContextCompat.getColor(getActivity(), R.color.accentline));
noviceline.setTextSize(12);
noviceline.setLineWidth(4);
I might style it up a bit more but so far the result looks like so:
There are a couple of options here.
You can see if the LimitLines will fit your purpose - they are able to be configured with a label like this:
LimitLine llXAxis = new LimitLine(10f, "Index 10");
llXAxis.setLineWidth(4f);
llXAxis.enableDashedLine(10f, 10f, 0f);
llXAxis.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM);
llXAxis.setTextSize(10f);
xAxis.addLimitLine(llXAxis);
You could also use a FrameLayout with over the chart with TextViews for the extra info you want to add. See this
question for something similar and also this question for how to convert between chart values and on-screen pixel co-ordinates.
Alternatively, you can extend the renderer itself to draw your custom text. Please see How do MPAndroidChart renderers work and how do I write a custom renderer? if you wish to attempt that.
I'm trying to set the width of the bars of a BarSeries with Shinobi.
Code's following:
DataAdapter<String, Double> da1 = new SimpleDataAdapter<String, Double>();
da1.add(new DataPoint<String, Double>("q1", 1.0));
da1.add(new DataPoint<String, Double>("q2", 3.0));
da1.add(new DataPoint<String, Double>("q3", 4.5));
da1.add(new DataPoint<String, Double>("q4", -2.5));
BarSeries series1 = new BarSeries();
series1.setDataAdapter(da1);
BarSeriesStyle css1 = series1.getStyle();
css1.setLineWidth(180.0f);
css1.setAreaColor(Color.YELLOW);
CategoryAxis xAxis = new CategoryAxis();
chart.setXAxis(xAxis);
xAxis.getStyle().setInterSeriesPadding(0.2f);
NumberAxis yAxis = new NumberAxis();
chart.setYAxis(yAxis);
yAxis.getStyle().setInterSeriesPadding(0.2f);
chart.addSeries(series1);
What happens is that the line css1.setLineWidth(180.0f); is completely ignored. I can put 1.0f or 1000.0f and the lines are always the same width no matter what.
What am I missing, or doing wrong? I'm using shinobi 1.5.1.
Edit: same goes with ColumnSeries:
ColumnSeries cs = new ColumnSeries();
DataAdapter<Float, Integer> adapterAxis = new SimpleDataAdapter<Float, Integer>();
adapterAxis.add(new DataPoint<Float, Integer>(0f, 3));
cs.getStyle().setLineColor(Color.BLACK);
cs.getStyle().setLineWidth(1f);
cs.setDataAdapter(adapterAxis);
1f or 20f, nothing changes.
chart.addSeries(cs);
Edit: following Kai's answer.
I tried playing around with setInterSeriesPadding, but it doesn't do what I need in that if I approach 1.f as padding value the bar will shrink, but if I set 0f the bar will have a minimum height and the space between them will remain 'big'.
To be clearer: I have 4 bars at 0 to 4 on the Y axis with different X values. Each one is centered more or less on the Y value (not really, but not important right now). E.g. bar centered in 2 will go from ~1.8 to ~2.2 and bar centered in 3 will go from ~2.8 to to ~3.2. I want them thicker, so that they go from ~1.55 to ~2.45 and from ~2.55 to ~3.45. How do I do that?
Edit 2 (images):
Actual:
Desired (sorry for my lack of Paint skills, it was just a way to show that I want them thicker):
When you refer to width of a bar series, I am going to assume you mean the height, i.e. measuring from the top to the bottom of the bar. I'd like to mention that the setLineWidth() method is not intended for this purpose, but in fact this method is used to style the line which is drawn around the edge of a bar (or column) to act as a border. As the value passed to this method is increased, the bars (or columns) remain the same size, but the line grows inward. Subsequently, a large number will give the appearance of no line, as the bar or column will have a line so thick that it fills the entire bar (or column).
If you wish to manipulate the height of the bars (or the width of the columns) you need to use the methods:
http://www.shinobicontrols.com/docs/ShinobiControls/ShinobiChartsAndroid/1.5.1/Premium/Normal/apidocs/docs/reference/com/shinobicontrols/charts/AxisStyle.html#setInterSeriesPadding(float)
and
http://www.shinobicontrols.com/docs/ShinobiControls/ShinobiChartsAndroid/1.5.1/Premium/Normal/apidocs/docs/reference/com/shinobicontrols/charts/AxisStyle.html#setInterSeriesSetPadding(float)
I hope that you find this information useful. Thanks and kind regards,
Kai.
EDIT:
Hello Stephen,
Thanks for the extra information.
So today I created a quick app, using your code to populate a Shinobi chart with data.
I did see the thin bars issue which you describe. I believe in order to correct this you also need to call the method Axis.setInterSeriesSetPadding(float).
Although when you use a single series in your chart it is not obvious, this method does affect the spacing between individual bars. By default there is a small spacing between bars if this method is not explicitly called.
Please remember also that these two methods expect a float value between 0 (no padding at all) and 1. I suggest you call both of these methods with a parameter of 0.0 and slowly increase the values until you achieve the appearance you wish. You should only need to call these 2 methods on your category axis, not the data axis.
Whilst building my app with your code I did notice that you use a bar series, but you have your category axis on the x axis. I found when I built my app it initially only displayed 3 bars as the first category ("q1") was rendered as having a zero data value. This is because categories are internally given an integer index, and so the first category is stored with a 0 index.
The typical way to use a bar series is to have the categories on the y axis and the data values on the x axis. I modified my app to use this configuration and I found all 4 bars showed correctly. Furthermore I was able to have a padding ranging from nothing, where the bars were butted up against each other, to a lot of padding where the bars appear thin.
I hope that this helps,
Thanks,
Kai.
Disclaimer: I work for ShinobiControls.
I'm using android graphview 3.1.1. I am trying to set an axis label, a label identifying what the axis is.
The only thing I've found close to this in Android GraphView is setting individual tick-mark labels as withgraphView.setHorizontalLabels(horlabels). Is it possible to set the entire label?
Example here, the axis labels are Month and Weight in Kg.
I have had a similar problem, so I set a by -90° rotated TextView beside my LinearLayout where i draw the graph.
<TextView
android:layout_height="fill_parent"
android:layout_width="wrap_content"
android:id="#+id/test"
android:textColor="#FFFFFF"
android:gravity="center"
android:rotation="-90"
android:textSize="12dp"
android:text="°C"/>
The problem with this method: The width of my rotated TextView stays the same like if's not rotated. So there is a huge amount of space to the left and right if you use a long text. If you shorten the layout_widht there is a line break.
For short text it looks nice: http://i.stack.imgur.com/KWMk8.jpg
there is no build-in feature for that, but you can achieve this by nesting the GraphView-View in layouts with TextViews
There are no ways provided to set the entire label. You may have to do this with TextViews.