Mpandroidchart: How to add String label to x and y axes?

Created on 23 Nov 2014  ·  16Comments  ·  Source: PhilJay/MPAndroidChart

I am developing a simple Android app which shows a dataset of flot numbers on a linechart through your library MPAndroidChart and thanks to it I am able to manage my custom linechart and its style.

However, I am trying to add a String Label in order to label both the domain (x-axes) and the range (y-axes) of my linechart, as shown in the picture below.
example

Any suggestions to do it using MPAndroidChart?
Thank you for your time

Most helpful comment

how to set in v3.0.1

All 16 comments

could you paste your code ?

of course AmintP8745.
Here the activity which manages the linechart. I have just copied and pasted the example and get the main aspects.

import android.support.v7.app.ActionBarActivity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.Toast;

import com.github.mikephil.charting.charts.BarLineChartBase.BorderPosition;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.OnChartGestureListener;
import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener;
import com.github.mikephil.charting.utils.Legend;
import com.github.mikephil.charting.utils.Legend.LegendForm;
import com.github.mikephil.charting.utils.Legend.LegendPosition;
import com.github.mikephil.charting.utils.XLabels;
import com.github.mikephil.charting.utils.XLabels.XLabelPosition;
import com.github.mikephil.charting.utils.YLabels;

import it.antedesk.util.MyMarkerView;

import java.util.ArrayList;

public class LineChartActivity1 extends ActionBarActivity implements OnChartGestureListener, OnChartValueSelectedListener {

private LineChart mChart;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(R.layout.activity_linechart);

    mChart = (LineChart) findViewById(R.id.chart1);
    mChart.setOnChartGestureListener(this);
    mChart.setOnChartValueSelectedListener(this);

    //      mChart.setUnit(" $");
    mChart.setDrawUnitsInChart(true);

    // if enabled, the chart will always start at zero on the y-axis
    mChart.setStartAtZero(true);

    mChart.setDrawBorder(false);
    mChart.setBorderPositions(new BorderPosition[] {
            BorderPosition.TOP
    });

    // enable / disable grid background
    mChart.setDrawGridBackground(true);

    // enable value highlighting
    mChart.setHighlightEnabled(false);

    // enable touch gestures
    mChart.setTouchEnabled(true);

    // enable scaling and dragging
    mChart.setDragEnabled(true);
    mChart.setScaleEnabled(true);

    // if disabled, scaling can be done on x- and y-axis separately
    mChart.setPinchZoom(true);

    // set an alternative background color
    mChart.setBackgroundColor(Color.TRANSPARENT);

    // create a custom MarkerView (extend MarkerView) and specify the layout
    // to use for it
    MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view);

    // define an offset to change the original position of the marker
    // (optional)
    mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight());

    // set the marker to the chart
    mChart.setMarkerView(mv);

    XLabels xLabels = mChart.getXLabels();
    xLabels.setPosition(XLabelPosition.BOTTOM);
    xLabels.setAvoidFirstLastClipping(true);    

    mChart.setDrawYLabels(true);

    // add data
    setData(15, 100);

    mChart.animateXY(3000, 3000);

    // get the legend (only possible after setting data)
    Legend l = mChart.getLegend();

    // modify the legend ... by default it is on the left
    l.setPosition(LegendPosition.BELOW_CHART_CENTER);
    l.setForm(LegendForm.SQUARE);


    // // dont forget to refresh the drawing
    // mChart.invalidate();
}


@Override
public void onChartLongPressed(MotionEvent me) {
    Log.i("LongPress", "Chart longpressed.");
}

@Override
public void onChartDoubleTapped(MotionEvent me) {
    Log.i("DoubleTap", "Chart double-tapped.");
}

@Override
public void onChartSingleTapped(MotionEvent me) {
    Log.i("SingleTap", "Chart single-tapped.");
}

@Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
    Log.i("Fling", "Chart flinged. VeloX: " + velocityX + ", VeloY: " + velocityY);
}

@Override
public void onValueSelected(Entry e, int dataSetIndex) {
    Log.i("Entry selected", e.toString());
}

@Override
public void onNothingSelected() {
    Log.i("Nothing selected", "Nothing selected.");
}



private void setData(int count, float range) {

    ArrayList<String> xVals = new ArrayList<String>();
    for (int i = 0; i < count; i++) {
        xVals.add((i) + "");
    }

    ArrayList<Entry> yVals = new ArrayList<Entry>();

    for (int i = 0; i < count; i++) {
        float mult = (range + 1);
        float val = (float) (Math.random() * mult) + 3;// + (float)
        // ((mult *
        // 0.1) / 10);
        yVals.add(new Entry(val, i));
    }
    xVals.add("15");

    // create a dataset and give it a type
    LineDataSet set = new LineDataSet(yVals, "Test set");

    set.setColor(Color.GREEN);
    set.setCircleColor(Color.BLACK);
    set.setLineWidth(2f);
    set.setCircleSize(3f);
    set.setFillAlpha(10);
    set.setFillColor(Color.BLACK);
    set.setDrawCubic(true);
    set.setDrawCircles(false);


    ArrayList<LineDataSet> dataSets = new ArrayList<LineDataSet>();
    dataSets.add(set); // add the datasets

    // create a data object with the datasets
    LineData data = new LineData(xVals, dataSets);


    // set data
    mChart.setData(data);
}

}

I suggest that you either use additional TextViews outside the chart or modify the library to your purpose.

It's currently not supported by default.

It is what I have done while I was waiting for your answare.
Thank you for your time and solution.

PS: If you want to, I can suggest you some other feature to improve your wonderful libs.

is it possible to draw custom axes. i like to create it as coordinate system means origin should be in middle of the graph. thanks in advance.

Hi,Could you please tell me how did you add the feature into this libs? I am meeting the same problem...

Hey, I used this lib for a project last year. In the end I came to the conclusion that the library didn't support this, so we had to have a textview representation of the chart below it, if that makes sense

Date: Mon, 23 Nov 2015 18:36:51 -0800
From: [email protected]
To: [email protected]
CC: [email protected]
Subject: Re: [MPAndroidChart] How to add String label to x and y axes? (#234)

Hi,Could you please tell me how did you add the feature into this libs? I am meeting the same problem...


Reply to this email directly or view it on GitHub.

how to set in v3.0.1

@antedesk Plz can u post ur solution here ?

Is the feature added in the new version?

if you want to show value over dot this is method

    mLineChart.setDescription(null);
    mLineChart.getAxisRight().setEnabled(false);
    mLineChart.setClickable(false);
    mLineChart.setTouchEnabled(true);
    mLineChart.setPinchZoom(false);
    mLineChart.setDoubleTapToZoomEnabled(false);
    mLineChart.animateY(2000, Easing.EasingOption.EaseInOutCirc);
    mLineChart.setExtraOffsets(10, 20, 20, 10);


    mLineChart.getAxisRight().setAxisMinimum(0);
    YAxis leftAxis = mLineChart.getAxisLeft();
    leftAxis.setDrawGridLines(false);
    mLineChart.setBorderWidth(20f);
    leftAxis.setEnabled(true);
    leftAxis.setGranularity(1f);
    leftAxis.setTextColor(DeprecatedMethodCaller.getResourceColor(getActivity(), R.color.white));
    Legend legend = mLineChart.getLegend();
    legend.setEnabled(false);
    leftAxis.setDrawLabels(true);

      XAxis xAxis = mLineChart.getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setDrawGridLines(false);
        xAxis.setGranularity(1f);
        xAxis.setLabelCount(3);
        xAxis.setTextColor(DeprecatedMethodCaller.getResourceColor(getActivity(), R.color.white));
        YearXAxisFormatter xAxisFormatter = new YearXAxisFormatter();
        xAxisFormatter.setMonths(xData.toArray(new String[xData.size()]));
        xAxisFormatter.setChart(mLineChart);
        xAxis.setValueFormatter(xAxisFormatter);

        ArrayList<String> xData = new ArrayList<>();
        ArrayList valueSet = new ArrayList<>();

      for(int i =0 ; i < listData.size();i++){
            Data data = listData.get(i);
            String monthName  = "";
            try {
                 cal.setTime(f.parse(data.getLastUpdated()));
                 monthName  = new SimpleDateFormat("MMM ''yy", 
                                           Locale.getDefault()).format(cal.getTime());
            } catch (ParseException e) {
                e.printStackTrace();
            }
            xData.add(monthName);
            int value = Integer.valueOf((int) data.getScore());
            valueSet.add(new  Entry(i, value));
        }

        //set color
        LineDataSet barDataSet1 = new LineDataSet(valueSet, ".");
        barDataSet1.setDrawCircles(true);
        barDataSet1.setCircleRadius(4);
        LineData data = new LineData(barDataSet1);
        barDataSet1.setDrawFilled(true);
        data.setHighlightEnabled(true);
        data.setDrawValues(true);
        data.setValueTextSize(10);
        data.setValueTextColor(Color.rgb(255, 255, 255));
        xAxis.setAxisMinimum(data.getXMin() - 0.25f);
        xAxis.setAxisMaximum(data.getXMax() + 0.25f);
        YAxis leftAxis = mLineChart.getAxisLeft();
        if(data.getYMax() < 850) {
            leftAxis.setAxisMaximum(data.getYMax() + 50f);
        }else{
            leftAxis.setAxisMaximum(900f);
        }
        if(data.getYMin() > 600){
            leftAxis.setAxisMinimum(600f);
        }else{
            leftAxis.setAxisMinimum(data.getYMin() - 50f);
        }
           leftAxis.setSpaceTop(50f);
        mLineChart.setData(data);

Is it fixed in current version?

@antedesk @AmitP8745 @PhilJay @tejprakashtiwary @itzhangyang
How can i add Unit?

For the com.github.PhilJay:MPAndroidChart:v3.0.3

I am using a label list:

final List list_x_axis_name = new ArrayList<>();
list_x_axis_name.add("label1");
list_x_axis_name.add("label2");
list_x_axis_name.add("label3");
list_x_axis_name.add("label4");
list_x_axis_name.add("label5");

and setting the label like this:

BarChart chartBar = (BarChart) findViewById(R.id.chartBar);
XAxis xAxis = chartBar.getXAxis();
xAxis.setGranularity(1f);
xAxis.setCenterAxisLabels(true);
xAxis.setLabelRotationAngle(-90);
xAxis.setValueFormatter(new IAxisValueFormatter() {
 @override
 public String getFormattedValue(float value, AxisBase axis) {
  if (value >= 0) {
   if (value <= list_x_axis_name.size() - 1) {
    return list_x_axis_name.get((int) value);
   }
   return "";
  }
  return "";
 }
});

You can easily do using this method...

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.TextView;

@SuppressLint("AppCompatCustomView")
public class VerticalTextView extends TextView {

public final static int ORIENTATION_UP_TO_DOWN = 0;
public final static int ORIENTATION_DOWN_TO_UP = 1;
public final static int ORIENTATION_LEFT_TO_RIGHT = 2;
public final static int ORIENTATION_RIGHT_TO_LEFT = 3;

Rect text_bounds = new Rect();
private int direction;

public VerticalTextView(Context context) {
    super(context);
}

public VerticalTextView(Context context, AttributeSet attrs) {
    super(context, attrs);

    TypedArray a = context.obtainStyledAttributes(attrs,
            R.styleable.verticaltextview);
    direction = a.getInt(R.styleable.verticaltextview_direction, 0);
    a.recycle();

    requestLayout();
    invalidate();

}

public void setDirection(int direction) {
    this.direction = direction;

    requestLayout();
    invalidate();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    getPaint().getTextBounds(getText().toString(), 0, getText().length(),
            text_bounds);
    if (direction == ORIENTATION_LEFT_TO_RIGHT
            || direction == ORIENTATION_RIGHT_TO_LEFT) {
        setMeasuredDimension(measureHeight(widthMeasureSpec),
                measureWidth(heightMeasureSpec));
    } else if (direction == ORIENTATION_UP_TO_DOWN
            || direction == ORIENTATION_DOWN_TO_UP) {
        setMeasuredDimension(measureWidth(widthMeasureSpec),
                measureHeight(heightMeasureSpec));
    }

}

private int measureWidth(int measureSpec) {
    int result = 0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    if (specMode == MeasureSpec.EXACTLY) {
        result = specSize;
    } else {
        result = text_bounds.height() + getPaddingTop()
                + getPaddingBottom();
        // result = text_bounds.height();
        if (specMode == MeasureSpec.AT_MOST) {
            result = Math.min(result, specSize);
        }
    }
    return result;
}

private int measureHeight(int measureSpec) {
    int result = 0;
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

    if (specMode == MeasureSpec.EXACTLY) {
        result = specSize;
    } else {
        result = text_bounds.width() + getPaddingLeft() + getPaddingRight();
        // result = text_bounds.width();
        if (specMode == MeasureSpec.AT_MOST) {
            result = Math.min(result, specSize);
        }
    }
    return result;
}

@Override
protected void onDraw(Canvas canvas) {

// super.onDraw(canvas);

    canvas.save();

    int startX = 0;
    int startY = 0;
    int stopX = 0;
    int stopY = 0;
    Path path = new Path();
    if (direction == ORIENTATION_UP_TO_DOWN) {
        startX = (getWidth() - text_bounds.height() >> 1);
        startY = (getHeight() - text_bounds.width() >> 1);
        stopX = (getWidth() - text_bounds.height() >> 1);
        stopY = (getHeight() + text_bounds.width() >> 1);
        path.moveTo(startX, startY);
        path.lineTo(stopX, stopY);
    } else if (direction == ORIENTATION_DOWN_TO_UP) {
        startX = (getWidth() + text_bounds.height() >> 1);
        startY = (getHeight() + text_bounds.width() >> 1);
        stopX = (getWidth() + text_bounds.height() >> 1);
        stopY = (getHeight() - text_bounds.width() >> 1);
        path.moveTo(startX, startY);
        path.lineTo(stopX, stopY);
    } else if (direction == ORIENTATION_LEFT_TO_RIGHT) {
        startX = (getWidth() - text_bounds.width() >> 1);
        startY = (getHeight() + text_bounds.height() >> 1);
        stopX = (getWidth() + text_bounds.width() >> 1);
        stopY = (getHeight() + text_bounds.height() >> 1);
        path.moveTo(startX, startY);
        path.lineTo(stopX, stopY);
    } else if (direction == ORIENTATION_RIGHT_TO_LEFT) {
        startX = (getWidth() + text_bounds.width() >> 1);
        startY = (getHeight() - text_bounds.height() >> 1);
        stopX = (getWidth() - text_bounds.width() >> 1);
        stopY = (getHeight() - text_bounds.height() >> 1);
        path.moveTo(startX, startY);
        path.lineTo(stopX, stopY);
    }

    this.getPaint().setColor(this.getCurrentTextColor());

// canvas.drawLine(startX, startY, stopX, stopY, this.getPaint());
canvas.drawTextOnPath(getText().toString(), path, 0, 0, this.getPaint());

    canvas.restore();
}

}

////////////////// Then go to XML File and call this class, where you want to modify the textview like below

android:id="@+id/txt_and_chart"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="@id/title_layout"

    >
    <LinearLayout

        android:layout_below="@+id/toolbar_layout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        >
        <com.example.smarthome.VerticalTextView
            android:layout_width="wrap_content"
            android:layout_height="180dp"
            android:layout_alignParentLeft="true"
            android:layout_below="@+id/title_layout"
            android:background="#455a64"
            android:padding="10dp"
            android:layout_marginTop="60dp"
            android:text="Lux Value (Y)"
            android:textStyle="bold"
            android:textColor="@android:color/white"
            android:textSize="20sp"
            app:direction="downtoup" />



    </LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:id="@+id/graph_layout"
    >

    <com.github.mikephil.charting.charts.LineChart
        android:layout_width="match_parent"
        android:layout_height="500dp"
        android:id="@+id/sensor_linechart"
        android:layout_below="@id/title_layout"
        android:layout_marginLeft="0dp"
        >
    </com.github.mikephil.charting.charts.LineChart>
</LinearLayout>
</LinearLayout>

Hey @antedesk, I have a question to your chart.
How do you add the titles (Range and Domain) on the side? I need a text like this.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Nima9Faraji picture Nima9Faraji  ·  3Comments

chathudan picture chathudan  ·  3Comments

OnlyInAmerica picture OnlyInAmerica  ·  3Comments

AiTheAnswer picture AiTheAnswer  ·  3Comments

Giammaofwar picture Giammaofwar  ·  3Comments