0
votes

I'm using MPAndroidChart library for charts in android studio. The charts are displaying fine in activities but i'm unable to use them in fragments. Tried using different charts but i'm unable to solve the issue. I'm getting a message "No chart data available" even though i'm giving data to the chart. So basically i have an activity (with bottom navigation bar) called ExamPerformanceActivity which has three fragments MathsFragment, PhysicsFragment, ChemistryFragment. I'm having a bar chart in MathsFragment where i'm facing the problem.

activity_exam_performance.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.peepstake.vijay.statlog.ExamPerfoActivity">

<FrameLayout
    android:id="@+id/frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@+id/navigation"
    android:animateLayoutChanges="true">
</FrameLayout>

<android.support.design.widget.BottomNavigationView
    android:id="@+id/navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="@color/colorPrimary"
    app:itemIconTint="#d5d6d9"
    app:itemTextColor="#ffffff"
    app:menu="@menu/bottombar_student_items"/>
  </RelativeLayout>

ExamPerformanceActivity.java

public class ExamPerformanceActivity extends AppCompatActivity {



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

    BottomNavigationView bottomNavigationView = (BottomNavigationView)
            findViewById(R.id.navigation);

    bottomNavigationView.setOnNavigationItemSelectedListener
            (new BottomNavigationView.OnNavigationItemSelectedListener() {
                @Override
                public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                    Fragment selectedFragment = null;
                    switch (item.getItemId()) {
                        case R.id.maths:
                            selectedFragment = MathsFragment.newInstance();
                            break;
                        case R.id.physics:
                            selectedFragment = PhysicsFragment.newInstance();
                            break;
                        case R.id.chemistry:
                            selectedFragment = ChemistryFragment.newInstance();
                            break;
                    }
                    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                    transaction.replace(R.id.frame_layout, selectedFragment);
                    transaction.commit();
                    return true;
                }
            });

    //Manually displaying the first fragment - one time only
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.frame_layout, MathsFragment.newInstance());
    transaction.commit();

    //Used to select an item programmatically
    //bottomNavigationView.getMenu().getItem(2).setChecked(true);

}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        // Respond to the action bar's Up/Home button
        case android.R.id.home:
            NavUtils.navigateUpFromSameTask(this);
            return true;
    }
    return super.onOptionsItemSelected(item);
}
public void goTopicwise(View v){
    Intent intent = new Intent(ExamPerformanceActivity.this, TopicwiseActivity.class);
    startActivity(intent);
}

}

fragment_maths.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.peepstake.vijay.statlog.Common.MathsFragment">


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

</FrameLayout>

MathsFragment.java

public class MathsFragment extends Fragment {
BarChart bar;

public static MathsFragment newInstance() {
    MathsFragment fragment = new MathsFragment();
    return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

public MathsFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment

    View view =inflater.inflate(R.layout.fragment_maths, container, false);

    Typeface font = Typeface.createFromAsset(getActivity().getAssets(), "fonts/ProductSans.ttf");

    bar = (BarChart)view.findViewById(R.id.bar);

    List<BarEntry> entries = new ArrayList<>();
    entries.add(new BarEntry(0f, 100f,"Total"));
    entries.add(new BarEntry(1f, 82f,"Obtained"));
    entries.add(new BarEntry(2f, 95f,"Highest"));
    entries.add(new BarEntry(3f, 69f,"Average"));



    BarDataSet bSet = new BarDataSet(entries, "Marks");
    bSet.setColors(ColorTemplate.VORDIPLOM_COLORS);

    ArrayList<String> barFactors = new ArrayList<>();
    barFactors.add("Total");
    barFactors.add("Obtained");
    barFactors.add("Highest");
    barFactors.add("Average");


    XAxis xAxis = bar.getXAxis();
    xAxis.setGranularity(1f);
    xAxis.setGranularityEnabled(true);
    BarData data = new BarData(bSet);
    data.setBarWidth(0.9f); // set custom bar width
    data.setValueTextSize(12);
    Description description = new Description();
    description.setTextColor(R.color.colorPrimary);
    description.setText("All values in marks");
    bar.setDescription(description);
    bar.setData(data);
    bar.setFitBars(true); // make the x-axis fit exactly all bars
    bar.invalidate(); // refresh
    bar.getXAxis().setValueFormatter(new IndexAxisValueFormatter(barFactors));

    Legend l = bar.getLegend();
    l.setFormSize(10f); // set the size of the legend forms/shapes
    l.setForm(Legend.LegendForm.CIRCLE); // set what type of form/shape should be used
    l.setTypeface(font);
    l.setTextSize(12f);
    l.setTextColor(Color.BLACK);
    List<LegendEntry> lentries = new ArrayList<>();
    for (int i = 0; i < barFactors.size(); i++) {
        LegendEntry entry = new LegendEntry();
        entry.formColor = ColorTemplate.VORDIPLOM_COLORS[i];
        entry.label = barFactors.get(i);
        lentries.add(entry);
    }
    l.setXEntrySpace(5f); // set the space between the legend entries on the x-axis
    l.setYEntrySpace(5f);
    l.setCustom(lentries);

    return inflater.inflate(R.layout.fragment_maths, container, false);
}

}

My Output screen

1

1 Answers

2
votes

Change the last line of your onCreateView method to the following:

l.setCustom(lentries);
//return inflater.inflate(R.layout.fragment_maths, container, false);
return view;

The chart will now display correctly:

a bar chart

Why? The first line of that method:

View view = inflater.inflate(R.layout.fragment_maths, container, false);

Inflates a View object which is the contentView for that Fragment.

You then call:

bar = (BarChart)view.findViewById(R.id.bar);

on that same View object to get a handle on the BarChart and then add the data to it.

However, in the original code at the end of the method, you inflate a new contentView and thereby discard the View and BarChart which you have added data. In other words the original method sets up the chart and then discards it, replacing it with an empty BarChart that is the simple result of inflating the View.