I want to display X-axis labels only on the top of my chart. How can I do it?
I'm using this code:
XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTH_SIDED);
xAxis.setDrawLabels(false);
And this is result:
Or If I do this
XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.TOP);
xAxis.setDrawAxisLine(true);
Then I have labels only on the top BUT the bottom line is missing.
You want to display xAxis lines for position BOTH_SIDED but without labels on the bottom, so you need to override XAxisRenderer:
chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTH_SIDED);
chart.setXAxisRenderer(new XAxisRenderer(chart.getViewPortHandler(), chart.getXAxis(), chart.getTransformer(YAxis.AxisDependency.LEFT)) {
#Override
public void renderAxisLabels(Canvas canvas) {
if (!mXAxis.isEnabled()|| !mXAxis.isDrawLabelsEnabled())
return;
MPPointF pointF = MPPointF.getInstance(0f, 0f);
mAxisLabelPaint.setTypeface(mXAxis.getTypeface());
mAxisLabelPaint.setTextSize(mXAxis.getTextSize());
mAxisLabelPaint.setColor(mXAxis.getTextColor());
pointF.x = 0.5f;
pointF.y = 1.0f;
drawLabels(canvas, mViewPortHandler.contentTop() - mXAxis.getYOffset(), pointF);
}
});
This won't help the original author, but I had the same issue and fixed it with
chart.setExtraBottomOffset(-40f);
Nice, simple, worth a try. You may need to tune the value to suit your aesthetic.
Related
I am a bit new to MPAndroidChart library and I am going to make a line chart for my data. I intend to set yaxis values exactly in the center of each grid rectangle which is inside them.
How that would be possible ?
I am actually trying to do this also,get the Y values show up above the graph in the center X axis, but I was having trouble. I know you have to override the draw method in your MarkerView class, the code I was using is below. Maybe you can play with it and get the results you need. Other questions about this I was looking at had posX = getXoffset() & posY = 0 but for some reason I wasn't able to get the getXoffset() Override method.
#Override
public void draw(Canvas canvas, float posX, float posY) {
posX = 400;
posY = -30;
canvas.translate(posX,posY);
draw(canvas);
canvas.translate(-posX,-posY);
}
I am not getting what exactly do you want. Try this:
lineChart.getXAxis().setCenterAxisLabels(true);
Right Now I am facing this issue. I am getting repeated values in xAxis the first one and the last one.And graph values are not according to the values at respective x-axis values.
and the second issue is if I want to display the values not in float but in int Rounded and change the their color to white.
ArrayList<String> xlabels = new ArrayList<String>();
xlabels.add("Jan");
xlabels.add("Feb");
xlabels.add("Mar");
xlabels.add("Apr");
xlabels.add("May");
xlabels.add("Jun");
ArrayList<String> values = new ArrayList<String>();
values.add("1");
values.add("20");
values.add("10");
values.add("80");
values.add("90");
values.add("24");
showLineChart(clickChart,xlabels,values,mColors[3]);
showLineChart Method:
private void showLineChart(LineChart chart,final List<String> xLabels, List<String> values,int color){
List<Entry> entries = new ArrayList<Entry>();
for(int i=0;i<values.size();i++){
entries.add(new Entry(i, Integer.parseInt(values.get(i))));
}
LineDataSet dataSet = new LineDataSet(entries, "Numbers");
dataSet.setLineWidth(1.75f);
dataSet.setCircleRadius(5f);
dataSet.setCircleHoleRadius(2.5f);
dataSet.setColor(Color.WHITE);
dataSet.setCircleColor(Color.WHITE);
dataSet.setHighLightColor(Color.WHITE);
dataSet.setDrawValues(true);
LineData data = new LineData(dataSet);
((LineDataSet) data.getDataSetByIndex(0)).setCircleColorHole(color);
chart.getDescription().setEnabled(false);
chart.setDrawGridBackground(false);
chart.setTouchEnabled(true);
chart.setBorderColor(Color.WHITE);
chart.setDragEnabled(true);
chart.setScaleEnabled(true);
chart.setPinchZoom(false);
chart.setBackgroundColor(color);
YAxis yAxisLeft = chart.getAxisLeft();
yAxisLeft.setTextColor(Color.WHITE);
yAxisLeft.setAxisLineColor(Color.WHITE);
YAxis yAxisRight = chart.getAxisRight();
yAxisRight.setTextColor(Color.WHITE);
yAxisRight.setAxisLineColor(Color.WHITE);
XAxis xAxis = chart.getXAxis();
xAxis.setTextColor(Color.WHITE);
xAxis.setAxisLineColor(Color.WHITE);
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setAvoidFirstLastClipping(false);
xAxis.isDrawLabelsEnabled();
xAxis.setDrawGridLines(false);
xAxis.setValueFormatter(new IAxisValueFormatter() {
#Override
public String getFormattedValue(float value, AxisBase axis) {
return xLabels.get((int)value);
}
});
chart.animateX(2500);
chart.setData(data);
chart.invalidate();
}
I was facing the same issue to resolve it add the following line:
xAxis.setGranularityEnabled(true);
Check the link for more details about Axis.
Setting granularity alone did not solve my problem. Here's what I had to do:
XAxis xAxis = chart.getXAxis();
xAxis.setGranularity(1f);
xAxis.setGranularityEnabled(true);
xAxis.setLabelCount(xLabels.size(),false); // yes, false. This is intentional
xAxis.setValueFormatter(new MyXAxisValueFormatter(xLabels));
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
And, this is my simple implementation of the IAxisValueFormatter. You may change it as per your needs:
public class MyXAxisValueFormatter implements IAxisValueFormatter {
private ArrayList<String> mValues;
MyXAxisValueFormatter(ArrayList<String> values) {
this.mValues = values;
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
int index = Math.round(value);
if(index >= mValues.size()){
index = mValues.size()-1;
}
return mValues.get(index);
}
}
It's very important to know why every problem occurs and why the solution code solves the problem. So, here's the analysis part:
Why does this occur?
Even in cases where your data lies at whole number positions on the x-axis (0,1,2...), the actual label isn't necessarily placed at those specific positions. For example, the label for the data at 1.00f might be at 0.92f. (This is how the library handles it, not sure why). So, when you try to cast the float value to an int, you do not get the exact position. From the earlier example, the label at 0.92f when cast to an int would be a 0, not 1.
How does this code solve the problem?
If you understood the above section, then this must not be necessary. Anyways, here's the reasoning. From my test results, I noticed that the label position was at all times nearby the actual x. So, the Math.round() method was perfect to get the proper index out of the float value.
Additionally, I set the parameter forced as a false in the setLabelCount method because I wanted the labels to hide as the user zooms-in in the x-axis.
//set granularity to minimum value to ensure label does not give duplicate value
lineChart.getAxisLeft().setGranularity(1f);
lineChart.getXAxis().setGranularity(1f);
lineChart.getXAxis().setGranularityEnabled(true);
//also make sure you don't pass true as force parameter in below line please pass only false
bottomAxis.setLabelCount(dateLabels.size(),false);
I am using MPAndroid library for representing line and pie chart. When I use small values like 1,2,3,4.. at x-axis, The chart fit in screen and there is no need of scroll. But when data for x axis is large like date range (13-04-2016), So it gives me only 5 values instead of 10 on screen and when I zoom the chart then it shows all values in horizontal scroll. using below code
private void initializeChart(LineChart chart) {
// Chart view
chart.setDrawGridBackground(false);
chart.setDescription("");
chart.getLegend().setEnabled(true);
chart.setTouchEnabled(false);
int color = getResources().getColor(R.color.white);
chart.getAxisLeft().setTextColor(color); // left y-axis
chart.getXAxis().setTextColor(color);
//X axis
XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(false);
xAxis.setDrawLabels(true);
//Y axis
YAxis leftAxis = chart.getAxisLeft();
YAxis rightAxis = chart.getAxisRight();
rightAxis.setDrawLabels(false);
rightAxis.setDrawGridLines(false);
leftAxis.setDrawLabels(true);
leftAxis.setDrawGridLines(false);
ChartItem item = CannonJsonParser.parseCanonJson(act, act.res);
setLineData(10, 20, item);
// set data
chart.setData(lineData);
chart.getLegend().setEnabled(false);
//animate
// chart.animateX(2000, Easing.EasingOption.EaseInOutQuart);
chart.setDragEnabled(true);
chart.setTouchEnabled(true);
chart.setScaleXEnabled(true);
chart.setScaleYEnabled(false);
chart.setHighlightPerDragEnabled(false);
chart.setHighlightPerTapEnabled(false);
}
I want that either all data should be fixed on a single screen without scroll or if it scrolls then it should be scrollable without zooming graph. Right now when I zoom in the graph then only it scrolls and shows all data.
set AxisMaxValue(). It will show proper graph.
chart.getAxisLeft().setAxisMaxValue(float);
I want to set a vertical line in center of LineChart like this:
When scrolling to each point, it can notify to change the date below (the orange date field). And it can move left or right programmatically by click on arrow button.
Currently, I can set viewport and allow moving to center with this code:
LineData data = new LineData(xVals, dataSets);
mChart.setScaleMinima((float) data.getXValCount() / 7f, 1f);
mChart.moveViewTo(0, 7, YAxis.AxisDependency.LEFT);
And get the result:
How can I draw and set a vertical line like above?
Update:
For the listener, I think OnChartGestureListener onChartTranslate(MotionEvent me, float dX, float dY) may help. What I need is the distance between 2 points and how to calculate how many points are in current view port. Does anyone know that?
Have you tried using getEntryByTouchPoint on your chart supplying the x and y coordinates of the center of the chart?
public Entry getEntryByTouchPoint(float x, float y)
returns the Entry object displayed at the touched position of the chart
Take a look at the method
protected void drawGridBackground(Canvas c) {
in the BarLineChartBase class (parent for a LineChart). In that method you have all data to draw your line right in the middle.
Something like this
RectF rectF = mViewPortHandler.getContentRect();
float xMiddle = (rectF.right - rectF.left)/2;
Paint p = new Paint();
p.setColor(Color.BLACK);
c.drawLine(xMiddle, rectF.bottom, xMiddle, rectF.top, p);
Maybe it's too late but here is my answer. It's encoded in Swift using Charts (MPAndroidCharts port for iOS) but API is 99% the same ;)
let verticalPointEntry = ChartDataEntry(x: xValue, y: yValue)
let dataSet = LineChartDataSet(values: [verticalPointEntry], label: "")
dataSet.drawCirclesEnabled = false
dataSet.drawValuesEnabled = false
dataSet.setDrawHighlightIndicators(true)
dataSet.drawHorizontalHighlightIndicatorEnabled = false
dataSet.highlightColor = UIColor.white
dataSet.highlightLineWidth = 1
let highlightPoint = Highlight(x: xValue, y: yValue, dataSetIndex: datasetIndex)
self.highlightValues([highlightPoint])
// "yourNormalDataSet" is your regular dataSet in which you want to display vertical line over it
let chartData = LineChartData(dataSets: [yourNormalDataSet, dataSet])
self.data = chartData
self.data?.notifiyDataChanged()
self.notifyDataSetChanged
This will display a vercital line over the point defined by your xValue variable.
Hope it helps!
I am using MPChart for displaying a Barchart. My values are positive and negative. I want to show xAxis as used in Math of traditional way. Using this code my chart display vertical lines (only zero wanted)
mXAxis = mChart.getXAxis();
mXAxis.setDrawGridLines(false);
mXAxis.setEnabled(false);
mYAxis = mChart.getAxisLeft();
mYAxis.setDrawAxisLine(false);
mYAxis.setDrawGridLines(true);
mYAxis.setStartAtZero(false);
mYAxisRight = mChart.getAxisRight();
mYAxisRight.setEnabled(false);
mYAxisRight.setDrawGridLines(false);
Please, provide some sample for removing all horizontal lines but zero
EDIT:
Even when yAxis.setLabelCount(1) (1 because zero value needed to shown) the impl looks like:
public void setLabelCount(int yCount) {
if(yCount > 25) {
yCount = 25;
}
if(yCount < 2) {
yCount = 2;
}
this.mLabelCount = yCount;
}
So, is it recommended to override this implementation?
I have got solution with labels at bottom
Use this in your code
mXAxis = mChart.getXAxis();
mXAxis.setDrawGridLines(false);
mXAxis.setEnabled(true);
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);