Search code examples
androidlistviewandroid-listviewsimpleadapter

Trouble setting custom view in my ListAdapter


I have a list view with various element and that updates quite many times. I wanted to add a single seprator line after some random positions, like, after 3rd element, 7th element, 17th element, 19element etc.

so I desgined an xml file containing a seperator and inflate it on those position using custom SimpleAdapter. However, when I run my code , the seperator is added on weird positions and make my list looks too ugly and sometimmes gives Unfortunately, yourApp has stopped error

I have never worked with custom adapter before and have no idea what am I doing wrong.

This is my simple code and I have added comments for explanation,

public class SpecialAdapter extends SimpleAdapter {

    Context context;
    private LayoutInflater mInflater;


    public SpecialAdapter(Context context, ArrayList<HashMap<String, Object>> newsList, int resource,String[] from, int[] to) {
        super(context, newsList, resource, from, to);

        this.context = context;

        mInflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        View view = super.getView(position, convertView, parent);
        // TestApp.endPos holds the positions (it keep changing) after which i want to add                
        // separator
        if (position == TestApp.endPos){
            /* my Arraylist is of type HashMap<String, Object>
             * I have added an empty element and add the seperator view in                  
             * it.
             */
            TestApp.arrayList.add(new HashMap<String, Object>());
            // heads is an xml file of my separator
            view = mInflater.inflate(R.layout.heads, null);
        }

        return view;
    }

}

Can anyone help me how can I simplify my problem and what am I doing wrong ?


Solution

  • super.getView inflates as many views as can be visible at a single time. Later it will just re-use them.

    Since you later inflate your own layout, it is cached on top. In the end super.getView starts returning your custom views in random positions.

    To overcome this you need to tell the adapter that there are 2 types of views so it caches them both separately.

    Here are sample methods (not tested but should work):

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (position == TestApp.endPos) {
            // Handle separator views manually
            TestApp.arrayList.add(new HashMap<String, Object>());
    
            // If separator is not yet cached, create the view
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.heads, null);
            }
        } else {
            // Normal views are handled by the adapter
            convertView = super.getView(position, convertView, parent);
        }
    
        return convertView;
    }
    
    @Override
    public int getViewTypeCount() {
        // There are 2 types: separator and normal
        return 2;
    }
    
    @Override
    public int getItemViewType(int position) {
        if (position == TestApp.endPos) {
            // Separator view
            return 0;
        } else {
            // Normal view
            return 1;
        }
    }
    

    Note: having 2 types, means that 2 types of views will be cached and re-used.