Creating a Custom ListView References https://developer.android.com/guide/topics/ui/declaring-layout.html#adapterviews Overview The ListView in the previous tutorial creates a TextView object for each string in an array of strings. More often than not, we ll want to display more than just a string in each View object of the ListView. Moreover, we ll often have an ArrayList that holds references to objects of some custom class that we ve written. What we ll need is for the ListView to display, not a TextView, but a custom View for each object in the ArrayList. In order to make this happen we need to do a few things. 1. Create a custom View layout that specifies how to display the information in our custom class. 2. Create a custom ArrayAdapter that creates an instance of the custom View object for each object in the ArrayList 3. Attach the custom ArrayAdapter to the ListView. Creating a Custom View Layout Suppose we have a class named Message like the one below. public class Message {
private String sender; private String subject; private String text;... /* Constructors, getters, setter, etc. */ Suppose also that for each Message object, we want to display the sender and the subject in the ListView. Then the layout file, named message_view.xml, might look like the one below. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@id/messagesendertextview" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> <TextView android:id="@id/messagesubjecttextview" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> This layout file contains a horizontally oriented LinearLayout that contains two TextView objects, one to hold the message s sender and the other to hold the message s subject. Creating a Custom ArrayAdapter We re going to build a custom adapter that reads Message objects from an ArrayList<Message> object. For each Message in the ArrayList, it will populate the ListView with a View based on the custom layout we defined above. Creating a custom array adapter is easy. We just need to: 1. Create a new class that extends ArrayAdapter<Message> 2. Provide in it a constructor with a specific signature 3. Include an implementation of the getview() method The code for a file named MessageListAdapter.java is given below. The MessageListAdapter constructor takes a context, layout resource, and a reference to the ArrayList as arguments. The getview() method creates a new View object based on the custom layout we created earlier.
public class MessageListAdapter extends ArrayAdapter<Message> { private Context context; private int resource; private ArrayList<Message> messages; // local reference public MessageListAdapter(Context ctx, int res, ArrayList<Message> mssgs) { super(ctx, res, mssgs); this.context = ctx; this.resource = res; this.messages = mssgs; @Override public View getview(int position, View convertview, ViewGroup parent) { View view = convertview; if (view == null) { /* Create a new View object */ LayoutInflater li = (LayoutInflater) context.getsystemservice( Context.LAYOUT_INFLATER_SERVICE);
view = li.inflate(r.layout.message_view, null); /* Populate the View object */ Message message = messages.get(position); if (message!= null) { TextView v = (TextView) view.findviewbyid(r.id.messagesendertextview); v.settext(message.getsender() + : ); v = (TextView) view.findviewbyid(r.id.messagesubjecttextview); v.settext(message.getsubject()); /* Return the View object */ return view;
Setting the ListView Adapter Add a ListView widget to the layout file of the activity in which you wish the ListView to appear. In the example below we assume the id for the ListView is named messagelistview. In the oncreate() method of the activity that displays the ListView, after we initialize the messages ArrayList, we create an instance of our custom MessageListAdapter and pass it to the ListView s setadapter() method. ListView listview = (ListView) findviewbyid(r.id.messagelistview); MessageListAdapter adapter = new MessageListAdapter(this, android.r.layout.simple_list_item_1, messages); listview.setadapter(adapter); Modifying the ListView s onitemclicklistener Every onitemclick event from the ListView invokes the onitemclick() method in the onitemclicklistener. Passed to this listener is the position of the View that was clicked. This position directly corresponds to a position (index) of a Message in the messages ArrayList that was passed to the adapter s constructor. Therefore, every time a user presses a View in the ListView, we can get the original Message object in the messages ArrayList and use any of the data that is in the object.
For example, below I show a simple modification to the onitemclicklistner that starts a different activity when a View object in the ListView is pressed. Here, we assume the ListView is in a class named MessageList and we are starting an activity in a class named MessageEditor. Before calling startactivity() we put the Message object associated with the View that was pressed in the Intent. AdapterView.OnItemClickListener handler = new AdapterView.OnItemClickListener() { public void onitemclick(adapterview parent, View v, int position, long id) { Intent i = new Intent(MessageList.this, MessageEditor.class); i.putextra("message", messages.get(position)); startactivity(i); ;