Search code examples
androidandroid-layoutlistviewandroid-arrayadapter

Android - Listview with image and text


I just started learning android and I'm at a point where I want to do the question described below but I'm not sure how to start.

I have an array of data with the following data,

1, text1, image1.png
2, text2, image2.png
3, text3, null
4, null, image3.png

I know how to create a ListView with ArrayAdapter along with their xml layout following some tutorial.

As you see in the array above sometimes it doesn't contain an image, sometimes it doesn't contain text and sometimes it has both.

My question is how to make that work with layout so that it dynamically changes based on the array values?

In other words how can I start thinking about building a listview+ArrayAdapter+layout where I can view an imageiew only where the array record has an image only, viewing a textview when there is a text only and viewing both of them when both are available.

A link to a tutorial will be extremely helpful


Solution

  • You could create a type MyCustomType that represents one array element (In your case it holds a number, a text and an image). Furthermore you need to implement your custom array adapter. This adapter uses an ArrayList of your MyCustomType.

    public class CustomAdapter extends ArrayAdapter<MyCustomType> {
    
    //... 
    
    private ArrayList<MyCustomType> foo;
    
    public CustomAdapter(Context context, Activity bar, ArrayList<MyCustomType> foo) {
        super(bar, R.layout.row, foo);
    
        this.foo = foo;
        mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    

    Override getViewTypeCount() to determine how many different kinds of rows you have. getItemViewType returns the kind of row that has to be displayed.

    Your getView method could be similiar to his one:

    public View getView(int position, View convertView, ViewGroup parent) {
    
        ViewHolder viewHolder; 
        int type = getItemViewType(position); // decide what row type has to be displayed
    
        if (convertView == null) {              
            convertView = mInflater.inflate(R.layout.row, parent, false);
    
            viewHolder = new ViewHolder();
            viewHolder.number = //...
            viewHolder.text = //...
            viewHolder.image = //...
    
            convertView.setTag(viewHolder);
        }
        else {
            viewHolder = (ViewHolder) convertView.getTag(); // avoided to call findViewById
        }
    
    
        switch(type) {
        case TYPE1:
            //... you could just change the visibility of the corresponding view
            break;
        case TYPE 2:
            // ...
            break;
        }
    
        return convertView;
    }