Hot questions for Line Chart in MPAndroidChart

How to set padding between value labels and line for MPAndroidChart LineChart

Question: When I create a line chart with values for each point, the values on the chart overlap the line, as shown in the screenshot. Is there a function to add padding to the values to raise them up so that this doesn't happen? I've looked all over the place for an answer to this or even someone else having the same issue and haven't found what I'm looking for.

My current chart:

Answer: Based on this line in the source code:

int valOffset = (int) (dataSet.getCircleRadius() * 1.75f);

The padding is calculated based on the radius of the circle on the line, so my solution is to increase the size of the circle, set the outer radius to be transparent, and set the hole color to be the same as the line, which accomplishes what I want. This may not work for everyone, depending on what you're trying to do, but it worked in my case.


MPAndroidChart:Realtime Linechart Start from Right

Question: I am using real-time line chart, where graph data is moving from right to left, but the problem is graph is starting from Zero(0), because of that It looks like wrong data is coming, I want graph should start from the most right and start moving to the left

I have tried these but not working

 val leftAxis = chart.getAxisLeft()
 leftAxis.setEnabled(false)
 leftAxis.setStartAtZero(false)
 **OR**
 leftAxis.mAxisMinimum(3f)

Answer: Use following properties:

mChart?.xAxis?.spaceMin = 2.5f // As per you requiedment
mChart?.xAxis?.spaceMax = 0.1f // As per you requiedment 

How do I adjust what percentage of the graph is being used?

Question: I'm currently using a LineChart to display data as it is received. I want to show at most 360 points on the graph. (6 minutes, of once-per-second data) Since I want to indicate to the user how far along the data is on the 6-minute progress, I would like the line curve to only take up an appropriate amount of the graph. (Ie, 3 minutes of measurements should only take 50% of the available graph space)

What's currently happening:

What I'm trying to get:

Any help would be greatly appreciated!

Answer: I understand that you want to show full range for X axis.

XAxis x = mChart.getXAxis();
x.setAxisMinimum(min_value);
x.setAxisMaximum(max_value); // may be 360?

Android Studio - MPAndroidChart Add User Input to Line Graph

Question: I am trying to update my line graph using the data inputted by the user (through fragments).

MainFragment that gets user input

public class Fragment1 extends Fragment {

EditText Input;
Button EnterVal;
public float userInput;

//Fragment1Listener activityCommander;

public interface Fragment1Listener{
    void sendInput(float value);
}

/*@Override
public void onAttach(Context context) {
    super.onAttach(context);
    try{
        activityCommander = (Fragment1Listener) getTargetFragment();
    }catch (ClassCastException e){
        throw new ClassCastException(context.toString() + "Must Implement FragmentListener");
    }
}*/

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment1, container, false);

    //@SuppressWarnings("all")

    Input = view.findViewById(R.id.Input);
    EnterVal = view.findViewById(R.id.button);


    EnterVal.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

            String val = Input.getText().toString();

            if(val != null && val.length() > 0) {
                userInput = Float.valueOf(val);
                Input.setText("");
                /*if(activityCommander != null) {
                    activityCommander.sendInput(userInput);
                }*/
                Fragment1Listener listener = getListener();
                if(listener != null){
                    listener.sendInput(userInput);
                    Log.d("User Val", "Listener was successfull!");
                }
            }
        }
    });

    return view;
}

@Nullable
private Fragment1Listener getListener(){
    Fragment1Listener activityCommander;
    try{
        Fragment onInputSelected_Frag = getTargetFragment();
        if(onInputSelected_Frag != null){
            activityCommander = (Fragment1Listener) onInputSelected_Frag;
        }
        else{
            Activity onInputSelected_Act = getActivity();
            activityCommander = (Fragment1Listener) onInputSelected_Act;
        }
        return activityCommander;
    }catch(ClassCastException e){
        Log.e("Fragment Listener", "getListener: ClassCastException + " + e.getMessage());
    }
    return null;
}
}

MPandroidchart Fragment (line graph)

public class Fragment2 extends Fragment implements Fragment1.Fragment1Listener{

private LineChart lineChart;
//public Fragment1 fragment1;

private ArrayList<ILineDataSet> DataSets = new ArrayList<>();
private LineDataSet lineDataSet5;
private ArrayList<Entry> userData = new ArrayList<>();
private LineData data = new LineData(DataSets);

@Override
public void sendInput(float value) {

    data = lineChart.getData();
    ILineDataSet xSet = data.getDataSetByIndex(0);

    data.addEntry(new Entry(xSet.getEntryCount(), value),0);

    //lineDataSet5.notifyDataSetChanged();
    //lineDataSets.add(lineDataSet5);
    data.notifyDataChanged();
    lineChart.notifyDataSetChanged();
    lineChart.invalidate();
    lineChart.moveViewToX(data.getEntryCount());
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment2, container, false);

    lineChart = view.findViewById(R.id.LineChart);

    //Enable Touch Gestures
    lineChart.setTouchEnabled(true);

    //We want also enable scaling and dragging
    lineChart.setDragEnabled(true);
    lineChart.setScaleEnabled(true);

    //Enable pinch zoom to avoid scaling x and y axis separately
    lineChart.setPinchZoom(true);

    //Double tap zoom to chart
    lineChart.setDoubleTapToZoomEnabled(true);

    //Alternate Background Color
    lineChart.setBackgroundColor(Color.parseColor("#2b2b2b"));

    ArrayList<String> xAXES = new ArrayList<>();
    ArrayList<Entry> yAXESsin = new ArrayList<>();
    ArrayList<Entry> yAXEScos = new ArrayList<>();
    ArrayList<Entry> yAXEStan = new ArrayList<>();
    ArrayList<Entry> random = new ArrayList<>();

    double x = 0;
    int numDataPoints = 1000;
    for(int i =0; i<numDataPoints; i++){
        float sinFunction = Float.parseFloat(String.valueOf(Math.sin(x)));
        float cosFunction = Float.parseFloat(String.valueOf(Math.cos(x)));
        float tanFunction = Float.parseFloat(String.valueOf(Math.tan(x)));
        x += 0.1;
        yAXESsin.add(new Entry(i, sinFunction));
        yAXEScos.add(new Entry(i, cosFunction));
        yAXEStan.add(new Entry(i, tanFunction));
        xAXES.add(i, String.valueOf(x));

        final int randomVal = getRandomNumber(-10, 10);
        float randomData = (float) randomVal;
        random.add(new Entry(i, randomData));
    }

    String[] xaxes = new String[xAXES.size()];
    for(int i =0; i<xAXES.size(); i++){
        xaxes[i] = xAXES.get(i).toString();
    }

    //Add user Input
    //@SuppressWarnings("all")
    //userInput = fragment1.getUserInput();
    //userData.add(new Entry(userData.size()+1, userInput));

    ArrayList<ILineDataSet> lineDataSets = new ArrayList<>();
    ArrayList<ILineDataSet> dataSets = new ArrayList<>();

    //Data Set 1

    LineDataSet lineDataSet1 = new LineDataSet(yAXEScos, "Cos");
    lineDataSet1.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineDataSet1.setDrawCircles(false);
    lineDataSet1.setColor(Color.parseColor("#B71C1C"));
    lineDataSet1.setLineWidth(3f);
    lineDataSet1.setHighlightEnabled(true);
    lineDataSet1.setDrawHighlightIndicators(true);
    lineDataSet1.setHighLightColor(Color.parseColor("#FF4081"));
    lineDataSet1.setValueTextSize(10f);
    lineDataSet1.setValueTextColor(Color.WHITE);
    lineDataSet1.setFillAlpha(110);

    //Data Set 2

    LineDataSet lineDataSet2 = new LineDataSet(yAXESsin, "Sin");
    lineDataSet2.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineDataSet2.setDrawCircles(false);
    lineDataSet2.setColor(Color.parseColor("#33bbff"));
    lineDataSet2.setLineWidth(3f);
    lineDataSet2.setHighlightEnabled(true);
    lineDataSet2.setDrawHighlightIndicators(true);
    lineDataSet2.setHighLightColor(Color.parseColor("#FFD600"));
    lineDataSet2.setValueTextSize(10f);
    lineDataSet2.setValueTextColor(Color.WHITE);
    lineDataSet2.setFillAlpha(110);

    //Data Set 3

    LineDataSet lineDataSet3 = new LineDataSet(yAXEStan, "Tan");
    lineDataSet3.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineDataSet3.setDrawCircles(false);
    lineDataSet3.setColor(Color.parseColor("#FFD600"));
    lineDataSet3.setLineWidth(3f);
    lineDataSet3.setHighlightEnabled(true);
    lineDataSet3.setDrawHighlightIndicators(true);
    lineDataSet2.setHighLightColor(Color.parseColor("#FFD600"));
    lineDataSet2.setValueTextSize(10f);
    lineDataSet2.setValueTextColor(Color.WHITE);
    lineDataSet2.setFillAlpha(110);

    //Data Set 4

    /*LineDataSet lineDataSet4 = new LineDataSet(random, "Random Numbers");
    lineDataSet4.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineDataSet4.setDrawCircles(false);
    lineDataSet4.setColor(Color.parseColor("#00897B"));
    lineDataSet4.setLineWidth(3f);
    lineDataSet4.setHighlightEnabled(true);
    lineDataSet4.setDrawHighlightIndicators(true);
    lineDataSet4.setHighLightColor(Color.parseColor("#64FFDA"));
    lineDataSet4.setValueTextSize(10f);
    lineDataSet4.setValueTextColor(Color.WHITE);
    lineDataSet4.setFillAlpha(110);*/

    //Data set 5 - User Input
    lineDataSet5 = new LineDataSet(userData, "User Data");
    lineDataSet5.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineDataSet5.setDrawCircles(false);
    lineDataSet5.setColor(Color.parseColor("#9C27B0"));
    lineDataSet5.setLineWidth(3f);
    lineDataSet5.setHighlightEnabled(true);
    lineDataSet5.setDrawHighlightIndicators(true);
    lineDataSet5.setHighLightColor(Color.parseColor("#E040FB"));
    lineDataSet5.setValueTextSize(10f);
    lineDataSet5.setValueTextColor(Color.WHITE);
    lineDataSet5.setFillAlpha(110);

    //Add Data sets
    lineDataSets.add(lineDataSet1);
    lineDataSets.add(lineDataSet2);
    lineDataSets.add(lineDataSet3);
    //lineDataSets.add(lineDataSet4);
    //lineDataSets.add(lineDataSet5);

    lineChart.setData(new LineData(lineDataSets));
    lineChart.setData(new LineData());
    lineChart.setVisibleXRangeMaximum(65f);
    lineChart.setHighlightPerTapEnabled(true);

    //Get legend object
    Legend legend = lineChart.getLegend();

    //Customize Legend
    legend.setForm(Legend.LegendForm.LINE);
    legend.setTextColor(Color.WHITE);

    //Set x axis
    XAxis xAxis = lineChart.getXAxis();
    xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
    xAxis.setTextColor(Color.WHITE);
    xAxis.setTextSize(10f);
    xAxis.setDrawGridLines(true);
    xAxis.setAvoidFirstLastClipping(true);

    //Set y axis
    YAxis yAxis = lineChart.getAxisLeft();
    yAxis.setTextColor(Color.WHITE);
    yAxis.setTextSize(10f);
    yAxis.setDrawGridLines(true);
    yAxis.setAxisMaximum(10f);
    yAxis.setAxisMinimum(-10f);

    //Disable Right y-axis values
    lineChart.getAxisRight().setEnabled(false);

    //Set Description
    lineChart.getDescription().setText("Sin and Cos Functions");
    lineChart.getDescription().setTextColor(Color.WHITE);

    //Update and refresh for User Input
    lineChart.notifyDataSetChanged(); //let the chart know it's data changed
    lineChart.invalidate(); //Refresh

    return view;
}

private int getRandomNumber(int min,int max) {
    return (new Random()).nextInt((max - min) + 1) + min;
}
}

MainActivity: It manages for 2 tabs, one tab contains the EditText for user to input their value, and the other tab contains the line graph that I want to be updated.

public class MainActivity extends AppCompatActivity {

private SectionsPagerAdapter mSectionsPagerAdapter;

private ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    // Set up the ViewPager with the sections adapter.
    mViewPager = findViewById(R.id.container);
    //mViewPager.setAdapter(mSectionsPagerAdapter);
    setupViewPager(mViewPager);

    TabLayout tabLayout = findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(mViewPager);

    mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
    tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

}

private void setupViewPager(ViewPager viewPager){
    SectionsPagerAdapter adapter = new SectionsPagerAdapter(getSupportFragmentManager());
    adapter.addFragment(new Fragment1(), "Fragment 1");
    adapter.addFragment(new Fragment2(), "Fragment 2");
    viewPager.setAdapter(adapter);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

Answer: You may be able to set the listener more directly. Try adding this method to Fragment1 (and removing getListener)

void setListener(Fragment1Listener listener) {
    activityCommander = listener;
}

then setting the listener in your Activity like this

private void setupViewPager(ViewPager viewPager){
    SectionsPagerAdapter adapter = new SectionsPagerAdapter(getSupportFragmentManager());
    Fragment1 f1 = new Fragment1();
    Fragment2 f2 = new Fragment2();
    f1.setListener(f2);
    adapter.addFragment(f1, "Fragment 1");
    adapter.addFragment(f2, "Fragment 2");
    viewPager.setAdapter(adapter);
}

There could be issues with this approach when the screen is rotated, but this should get you over this hurdle at least. If you want to continue using the getTargetFragment approach you'll need to call setTargetFragment somewhere too. Something like f1.setTargetFragment(f2); instead of f1.setListener(f2) in the code above.

I think you'll need to make some changes to the graph part once the listener is working to get it working still. For example, replace

lineChart.setData(new LineData(lineDataSets));
lineChart.setData(new LineData()); // this overrides the previous line with an empty data set

with

data.addDataSet([... the sets you want to add ...]);
lineChart.setData(data);

but this should get you started on the right path at least.


type variable T with upper bounds LineChart View

Question: I have the following class:

public class LineChart extends AppCompatActivity{
private LineChart mChart;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_line_chart);

    mChart = findViewById(R.id.linechart);
  }
}

And an XML:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_height="match_parent"
          android:layout_width="match_parent"
          android:id="@+id/relativeLayout">

<com.github.mikephil.charting.charts.LineChart
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/linechart">

</com.github.mikephil.charting.charts.LineChart>

My problem now is that when i try to get the Line Chart with findViewById(R.id.linechart) i get the error:

Error:(42, 24) error: incompatible types: no unique maximal instance exists for type variable T with upper bounds LineChart,View where T is a type-variable: T extends View declared in method findViewById(int)

If you look in the MPAndroidChart Wiki you will see that i did nothing wrong (i hope). Can someone tell me please where my mistake is. Thanks in advance

Answer: You should give your Activity a different name.

You have a conflict with the name LineChart so when you do the findViewById(...) lookup it thinks you want to use your LineChart instead of the one from the library you are using.

This is what is causing the incompatible types message since your LineChart does not extend View.


How to display the chart with real time in mpandroidchart?

Question: I am using MPAndroidChart I need to display the line chart with real time. But problem is, it's displaying after the entire completed one. Actually it should plot like real time. What I tried is,

private void updateUI(final ArrayList<TimeModel> pJsonObject) {

for(int i=0;i<pJsonObject.size();i++){
            int speedRates = pJsonObject.get(i).getSpeedRate();
            String time = String.valueOf(pJsonObject.get(i).getTotalTime());
            xAxes.add(time);
            //yAxes.add(new Entry(10, 0));
            yAxes.add(new Entry(speedRates,i));
        }
        String[] xaxes = new String[xAxes.size()];
        for (int i = 0; i < xAxes.size(); i++) {
            xaxes[i] = xAxes.get(i).toString();
        }

        LineDataSet lineDataSet = new LineDataSet(yAxes, "Time");

        lineDataSet.setDrawCircles(true);
        lineDataSet.setColor(Color.GREEN);

        lineDataSets.add(lineDataSet);

        linechart.setData(new LineData(xaxes, lineDataSets));
        linechart.setVisibleXRangeMaximum(65f);
//        linechart.setTouchEnabled(true);
//        linechart.setDragEnabled(true);

        linechart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);

        linechart.getAxisLeft().setDrawGridLines(false);
        linechart.getXAxis().setDrawGridLines(false);


        YAxis yAxisRight = linechart.getAxisRight();
        yAxisRight.setEnabled(false);

        linechart.animateXY(3000, 3000);
 }

But this is plotting as completed one. I need to plot as moving real time in mpandroid chart.

Answer: Here is code. It starts thread, then in loop you add entries to chart (500 points in this case), and after each adding, Thread sleeps for 1000 milliseconds (1 sec) and it is your interval:

    new Thread(new Runnable() {

        @Override
        public void run() {
            for(int i = 0; i < 500; i++) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        addEntry();
                    }
                });

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            }
        }
    }).start();

For just animation with interval of 1 second for each point use this

mChart.animateX(1000 * pointCount);

for example, in your case:

mChart.animateX(1000 * xAxes.size());

How to make empty space in a linechart?

Question: I'm using the MPAndroidChart librairy in my Android App and I'm drawing a LineChart like below.

Sometimes some entries (values) in my exemple are considered like invalid. I want to represent these values like a empty space that will be drawned between the last 2 valid entries something like

Answer: This can be done but you need combined chart for that and multiple lines will do the trick. Where you want to break end the 1st dataset there and from where begin again start 2nd dataset.

Follow example below:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    CombinedChart combinedChart = (CombinedChart) findViewById(R.id.chart1);
    CombinedData data = new CombinedData();
    data.setData(barData());
    data.setData(lineData());
    combinedChart.setData(data);

    // xAxis customization
    XAxis xAxis = combinedChart.getXAxis();

    // Following code have no effect but you can change it if required
    xAxis.setGranularity(1f);
    xAxis.setGranularityEnabled(true);
    xAxis.setCenterAxisLabels(false);
    xAxis.setDrawGridLines(false);

    // Setting maximum limit of xAxis
    xAxis.setAxisMaximum(barData().getEntryCount());

    // Setting position of xAxis
    xAxis.setPosition(XAxis.XAxisPosition.BOTH_SIDED);

    // This is used to fix bar width of first bar
    xAxis.setSpaceMin(barData().getBarWidth() / 2f);
    xAxis.setSpaceMax(barData().getBarWidth() / 2f);

    // Setting labels to xAxis
    xAxis.setValueFormatter(new IndexAxisValueFormatter(getXAxisValues()));

}

// creating list of x-axis values 
private ArrayList<String> getXAxisValues()
{
    ArrayList<String> labels = new ArrayList<String> ();

    labels.add( "JAN");
    labels.add( "FEB");
    labels.add( "MAR");
    labels.add( "APR");
    labels.add( "MAY");
    labels.add( "JUN");
    return labels; 
}

// this method is used to create data for line graph 
public LineData lineData()
{
    ArrayList<Entry> line = new ArrayList<Entry> ();
    line.add(new Entry(0, 10));
    line.add(new Entry(1, 11));
    line.add(new Entry(2, 12));
    line.add(new Entry(3, 14));
    line.add(new Entry(4, 18));
    line.add(new Entry(5, 31));

    LineDataSet lineDataSet = new LineDataSet(line, "Brand 2");
    lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT);
    lineDataSet.setColors(ColorTemplate.COLORFUL_COLORS);
    lineDataSet.setCircleRadius(5);

    // set this to false to disable the drawing of highlight indicator (lines)
    lineDataSet.setDrawHighlightIndicators(true);
    lineDataSet.setHighLightColor(Color.RED);
    LineData lineData = new LineData(lineDataSet);
    return lineData;
}

// this method is used to create data for Bar graph 
public BarData barData()
{
    ArrayList<BarEntry> group1 = new ArrayList<BarEntry>();
    group1.add(new BarEntry(0, 3));
    group1.add(new BarEntry(1, 1));
    group1.add(new BarEntry(2, 4));
    group1.add(new BarEntry(3, 7));
    group1.add(new BarEntry(4, 3));
    group1.add(new BarEntry(5, 8));

    BarDataSet barDataSet = new BarDataSet(group1, "Brand 1");
    barDataSet.setAxisDependency(YAxis.AxisDependency.RIGHT);
    //barDataSet.setColor(Color.rgb(0, 155, 0));
    barDataSet.setColors(ColorTemplate.COLORFUL_COLORS);

    BarData barData = new BarData(barDataSet);
    //        barData.setBarWidth(0.9f);

    return barData;
}
} 

Replace barData with your second line data in above example and also bar related things from code then you are good to go.


Can i create a Circle Hole over One that Already Exist in MpAndroid Line Chart?

Question: I am able to create the linechart dynamically using the MPAndroid Chart Library and is Able to Create the Shadow of the LineChart aswell but i am not Able to Create the Another Circle Hole Over the one previously existed in MPAndroid Line chart?

Code

  void plotGraph(List<StatementListApi> statementListApis) {

        HashMap<Integer, String> stringDoubleHashMap = new HashMap<>();
        stringDoubleHashMap.put(0, "0");
        stringDoubleHashMap.put(1, "0");
        stringDoubleHashMap.put(2, "0");
        stringDoubleHashMap.put(3, "0");
        stringDoubleHashMap.put(4, "0");
        stringDoubleHashMap.put(5, "0");
        stringDoubleHashMap.put(6, "0");

        for (int i = 0; i < statementListApis.size(); i++) {

            Date date = new Date(Long.parseLong(statementListApis.get(i).getRecordedDate()));
            System.out.println("date is" + date);

            if (stringDoubleHashMap.containsKey(date.getDay())) {

                Long aLong = statementListApis.get(i).getAmount() + Long.parseLong(stringDoubleHashMap.get(date.getDay()));

                stringDoubleHashMap.put(date.getDay(), aLong + "");

            } else {

                stringDoubleHashMap.put(date.getDay(), statementListApis.get(i).getAmount() + "");
            }
            System.out.println("size of hashmap" + stringDoubleHashMap.size());
        }


        List<String> xVals = new ArrayList<String>(stringDoubleHashMap.values());

        List<ILineDataSet> testDataSet1 = new ArrayList<>();

        List<Entry> entries = new ArrayList<>();

        ArrayList<String> Labels = new ArrayList<>();
        Labels.add("SUN");
        Labels.add("MON");
        Labels.add("TUE");
        Labels.add("WED");
        Labels.add("THU");
        Labels.add("FRI");
        Labels.add("SAT");

        for (int i = 0; i < xVals.size(); i++) {

            entries.add(new Entry(i, Float.parseFloat(xVals.get(i))));
            LineDataSet dataSet = new LineDataSet(entries, Labels.get(i));
            testDataSet1.add(dataSet);
            dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER);
            dataSet.setColor(Color.RED);
            dataSet.setCircleColor(Color.WHITE);
            dataSet.setValueTextColor(Color.WHITE);

        }


        activityStatementBinding.lineChart.getXAxis().setTextColor(Color.WHITE);

        // for shadow
        activityStatementBinding.lineChart.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        activityStatementBinding.lineChart.getRenderer().getPaintRender().setShadowLayer(1, 10, 10, Color.BLACK);

        IMarker marker = new CustomMarkerView(this, R.layout.activity_marker_view);
        activityStatementBinding.lineChart.setMarker(marker);

        MarkerImage markerImage = new MarkerImage(this, R.drawable.ic_back_24);
        activityStatementBinding.lineChart.setMarker(markerImage);

        //Animation
        activityStatementBinding.lineChart.animateY(1700);

        YAxis leftAxis = activityStatementBinding.lineChart.getAxisRight();
        leftAxis.setEnabled(false);

        //used to remove the horizontal x-axis lines in graph
        YAxis rightAxis = activityStatementBinding.lineChart.getAxisLeft();
        rightAxis.setEnabled(false);

        activityStatementBinding.lineChart.getDescription().setEnabled(false);

        activityStatementBinding.lineChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);

        // used for removing the labels with color
        Legend legend = activityStatementBinding.lineChart.getLegend();
        legend.setEnabled(false);


        activityStatementBinding.lineChart.getXAxis().setValueFormatter(new IndexAxisValueFormatter(Labels));
        activityStatementBinding.lineChart.setData(new LineData(testDataSet1));
        activityStatementBinding.lineChart.notifyDataSetChanged();
        activityStatementBinding.lineChart.invalidate();
    }

getting image

required image

How can i achieve the circle hole over the one that already exist?

Answer: you need to do following:

    lineDataSet.setCircleRadius(6);
    float circleHoleRadius = circleRadius/2;
    lineDataSet.setCircleHoleRadius(circleHoleRadius);
    //lineDataSet.setCircleColor(Color.RED);
    // Below line is to add transperancy to your color
    lineDataSet.setCircleColor(Color.argb(12,284,55,32));
    lineDataSet.setCircleColorHole(Color.WHITE);

You can change colors and size according to your requirements.


MPAndroidChart Line graph, line gets cut inbetween

Question: I have implemented Line chart and it is working perfectly. But for some values the line is not visible or its cut.

I have attached the screenshot. For value such as

[Entry, x: 0.0 y: 0.0, Entry, x: 1.0 y: 0.0, Entry, x: 2.0 y: 0.0, Entry, x: 3.0 y: 0.0, Entry, x: 4.0 y: 1.0, Entry, x: 5.0 y: 2.0, Entry, x: 6.0 y: 3.0] 

Is this issue with the Library ? As I have observed when the value changes from 0 to some greater value or from greater value to 0 line is cut.

LineChart lineChart = (LineChart) findViewById(R.id.chart);
lineChart.setDrawBorders(true);
lineChart.getDescription().setEnabled(false);
lineChart.fitScreen();
lineChart.setPadding(0,0,0,0);
lineChart.getLegend().setEnabled(false);
lineChart.setDoubleTapToZoomEnabled(false);

lineChart.getAxisLeft().setEnabled(false);
lineChart.getAxisRight().setEnabled(true);
lineChart.getAxisLeft().setStartAtZero(true);

lineChart.getAxisRight().setDrawAxisLine(true);
lineChart.getAxisRight().setDrawLabels(true);
lineChart.getAxisRight().setDrawGridLines(false);

lineChart.getXAxis().setEnabled(true);
lineChart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);

lineChart.getXAxis().setDrawAxisLine(true);
lineChart.getXAxis().setDrawGridLines(true);
lineChart.setScaleMinima(3f, 0f);
lineChart.setBackgroundColor(Color.TRANSPARENT); //set whatever color you prefer
lineChart.setDrawGridBackground(false);
lineChart.setTouchEnabled(true);
lineChart.setDragEnabled(true);
lineChart.setScaleEnabled(true);
lineChart.setPinchZoom(false);
Legend l = lineChart.getLegend();
l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
l.setDrawInside(true);
ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();

ArrayList<Entry> values = new ArrayList<Entry>();
values.add(new Entry(Float.parseFloat("1"), 5));
values.add(new Entry(Float.parseFloat("2"), 2));
values.add(new Entry(Float.parseFloat("3"), 6));
values.add(new Entry(Float.parseFloat("4"), 8));
values.add(new Entry(Float.parseFloat("5"), 2));

LineDataSet d = new LineDataSet(values, "Actual kWh");
    d.setMode(LineDataSet.Mode.CUBIC_BEZIER);
    d.setLineWidth(1.5f);
    d.setCircleRadius(3f);
    d.setCircleColorHole(Color.BLACK);
    d.setValueTextSize(0f);
    d.setCircleColor(ContextCompat.getColor(mContext,R.color.blue_line));
    d.setColor(ContextCompat.getColor(mContext,R.color.blue_line));
    d.setDrawFilled(true);
    d.setFillDrawable(ContextCompat.getDrawable(mContext, R.drawable.graph_fill));
    dataSets.add(d);
LineData data = new LineData(dataSets);
lineChart.setData(data);
lineChart.invalidate();

Answer: I think your problem is related to d.setMode(LineDataSet.Mode.CUBIC_BEZIER);. The negative values are cut by your graph, and the Bezier interpolation creates a curve line that has little negative values between T and W.

Please try using a different mode (like a linear one d.setMode(LineDataSet.Mode.LINEAR);) or accept negative values (removing lineChart.getAxisLeft().setStartAtZero(true);).

With the mode LineDataSet.Mode.HORIZONTAL_BEZIER you can obtain the desired behaviour.