Ben
Ben

Reputation: 4867

Passing data to custom view in Android

I'm fairly new to Android and am trying to create a custom view to display a pie chart. I'm OK with Java and have written the pie chart code in iOS/Swift before.

My problem is that the data doesn't appear to get passed as I had expected, or perhaps that the onDraw function is getting called before the data is set somehow from the superclass.

I'd like to know the best method for passing data to be used in the onDraw function. So far, with a bit of help from posts like Android Custom View Constructor I've got the following code:

public PieChart(Context _context) {
    this(_context, null);
}
public PieChart(Context _context, AttributeSet _attrs) {
    this(_context, _attrs, null);
}
public PieChart(Context _context, AttributeSet _attrs, ArrayList<ChartData> _data) {
    super(_context, _attrs);
    if(this.isInEditMode()) {
        data = new ArrayList<ChartData>();
        data.add(new ChartData("Column A", 50));
        data.add(new ChartData("Column B", 75));
        data.add(new ChartData("Column C", 60));
    } else {
        data = _data;
    }
    context = _context;
    paint = new Paint();
    paint.setAntiAlias(true);
    paint.setStyle(Paint.Style.FILL);
    pieRectangle = new RectF(0,0,0,0);
    ...
}

Which is called from my activity like this:

// create the chart
PieChart pieChart = new PieChart(this, null, categoriesChartData);
// add the chart to the linearLayout
linearLayout.addView(pieChart);

And my PieChart.onDraw starts like this:

protected void onDraw(Canvas canvasChart) {
    Log.d(TAG, "Size of data = " + data.size()); // crashes here
    ...
}

Note that in the interface designer, the pie chart looks great, so I know the onDraw method works, it's simply that the data isn't making it there when the app is ran.

Rather than adding in extra functions and calls, as I don't have a lot of experience in Android, I'd like to ask the community what the problem is and what the best approach would be here.

Many thanks in advance!

Upvotes: 1

Views: 1348

Answers (3)

Enzokie
Enzokie

Reputation: 7415

Since using the constructor is not the ideal one; you can build a method that accepts an array of datas, in your case it is ArrayList<CharData> or List<CharData>.

public PieChart(Context _context) {
    this(_context, null);
}
public PieChart(Context _context, AttributeSet _attrs) {
    super(_context, _attrs);
    if(this.isInEditMode()) {
        data = new ArrayList<ChartData>();
        data.add(new ChartData("Column A", 50));
        data.add(new ChartData("Column B", 75));
        data.add(new ChartData("Column C", 60));
    }

    context = _context;
    paint = new Paint();
    paint.setAntiAlias(true);
    paint.setStyle(Paint.Style.FILL);
    pieRectangle = new RectF(0,0,0,0);
    ...
}

protected void onDraw(Canvas canvasChart) {
    if(data != null){
       Log.d(TAG, "Size of data = " + data.size());
       // more codes here
    }
}

public void setValues(List<CharData> d){
   data = d;
}

The final usecase would be like:

PieChart pieChart = new PieChart(this, null);
linearLayout.setValues(categoriesChartData);
linearLayout.addView(pieChart);

Upvotes: 1

zohreh
zohreh

Reputation: 1045

I think data is null because this.isInEditMode() return false.you should check it first.

Upvotes: -1

Dmitry Zaytsev
Dmitry Zaytsev

Reputation: 23952

Since you mentioned interface designer, I assume that you also added your view to XML layout. In that case Android View framework will use this constructor (by convention):

public PieChart(Context _context, AttributeSet _attrs)

That is the reason why your data is null. For views you have to create a setter method for your data instead of passing it as a constructor parameter.

Furthermore, if you already declared your view in XML layout, there is no need to create it manually - that will just add yet another view into layout.

Upvotes: 2

Related Questions