1

I need to use an ArrayAdapter to populate a ListView in my Android application. In order to use the ArrayAdapter, it says

For example, if you have an array of strings you want to display in a ListView, initialize a new ArrayAdapter using a constructor to specify the layout for each string and the string array:

ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, myStringArray);

The arguments for this constructor are:

  • Your app Context
  • The layout that contains a TextView for each string in the array
  • The string array

Then simply call setAdapter() on your ListView:

ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter);

However, I do not have an array of strings, I have an array of objects that contain string values.

public class Headers {
    private String from;
    private String to;
    private String subject;

    public Headers (String from, String to, String subject){
        this.from = from;
        this.to = to;
        this.subject = subject;
    }

    public String getFrom() { return from; }
    public void setFrom(String from) { this.from = from; }

    public String getTo() { return to; }
    public void setTo(String to) { this.to = to; }

    public String getSubject() { return subject; }
    public void setSubject(String subject) { this.subject = subject; }
}

My layout does contain a TextView corresponding to values in my object.

Here is my layout with my ListView:

<LinearLayout android:orientation="vertical">
    <ListView android:id="@+id/listOfHeaders" >
</LinearLayout>

And here is the layout for each row in the ListView to be populated by the ArrayAdapter:

<LinearLayout android:orientation="horizontal">
    <TextView android:id="@+id/toTextView" />
    <TextView android:id="@+id/fromTextView" />
    <TextView android:id="@+id/subjectTextView" />
</LinearLayout>
5
  • so use ArrayAdapter<Headers>, and not ArrayAdapter<String> Commented Apr 12, 2016 at 16:59
  • Yes, but then I need to populate my TextViews with the strings from the Headers object, and it looks like ListView wants an array of Strings. Commented Apr 12, 2016 at 17:01
  • 1
    not really, you can override getView method and do all the mappings (it is easier if you use ArrayAdapter(Context context, int resource, int textViewResourceId) ctor) Commented Apr 12, 2016 at 17:02
  • I have no idea how to implement the intricacies of that. Which is why I posted to StackOverflow. Commented Apr 12, 2016 at 17:38
  • 1
    just override getView, call super and see what super returns, then 3 simple findViewById should be enough Commented Apr 12, 2016 at 17:43

2 Answers 2

8

Using the ArrayAdapter is not enough, you will need to extend ArrayAdapter and create a custom adapter, so you can overwrite the rows creation to use your list layout. Please check this example:

public class CustomAdapter extends ArrayAdapter<Headers> {

    Context context;
    int layoutResourceId;
    ArrayList<Headers> data = null;

    public CustomAdapter(Context context, int resource, List<Headers> objects) {
        super(context, resource, objects);
        this.layoutResourceId = resource;
        this.context = context;
        this.data = (ArrayList) objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row = convertView;
        HeaderHolder holder = null;

        if(row == null)
        {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            row = inflater.inflate(layoutResourceId, parent, false);

            holder = new HeaderHolder();
            holder.from = (TextView) row.findViewById(R.id.fromTextView);
            holder.to = (TextView)row.findViewById(R.id.toTextView);
            holder.subject = (TextView)row.findViewById(R.id.subjectTextView);

            row.setTag(holder);
        }
        else
        {
            holder = (HeaderHolder) row.getTag();
        }

        Headers item = data.get(position);
        holder.from.setText(item.getFrom());
        holder.to.setText(item.getTo());
        holder.subject.setText(item.getSubject());

        return row;
    }

    private class HeaderHolder {
        public TextView from;
        public TextView to;
        public TextView subject;

    }
}

For the Activity, on the onCreate method:

ListView list = (ListView) findViewById(R.id.listView);
ArrayList<Headers> data = new ArrayList<Headers>();
data.add(new Headers("from", "to", "subject"));

ArrayAdapter adapter = new CustomAdapter(this, R.layout.list, data);
list.setAdapter(adapter); 

You can see that the CustomAdapter is using HeaderHolder as part of the ViewHolder pattern so the list management is efficient.

Sign up to request clarification or add additional context in comments.

3 Comments

That works fantastic, thanks! There is one issue, however. I sometimes get an IndexOutOfBoundsException on the line "Headers item = data.get(position)". Not always, but from time-to-time. I am using Fragments as tabs and I get this when I switch away from the fragment with my list.
Glad it helped. For the exception, add an if block to validate position before being used, or enclose those last lines in a try..catch block. It is a weird problem, but without the fragments code I am not sure what is causing it. Use one of the two suggestions to avoid the exception while you find the actual reason. Good luck on your project.
I ended up making a few changes to get rid of the error. I changed List<Headers> objects to Objects[] objects and used Header thisHeader = (Header) objects[position], and this seems to have fixed it. Thanks again for the help.
0

For your kind of info, you can actually do that by overriding getView() method. Basically you have to provide custom Layout for your ListView item and that you have to inflate in you getView() method. For more info you can link to this one: http://www.ezzylearning.com/tutorial/customizing-android-listview-items-with-custom-arrayadapter

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.