Sandman
Sandman

Reputation: 5580

Dynamic nested listviews in android

My app requires me display a dynamic nested listview. My outer listview is a series of jobs and interally each job contains a listview of lineitems required for it. I am using custom adapters to achieve dynamic nested listviews. Something like below:

LineItemCustomListViewAdaptor - loads the data items for a single job

JobCustomListViewAdaptor - loads the individual jobs by calling LineItemCustomListViewAdaptor on each job.

My getView function of the JobCustomListViewAdaptor is like this-

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

    LayoutInflater mInflater = (LayoutInflater) context
            .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.list_job, parent, false);
        holder = new ViewHolder();
        holder.jobnum = (TextView)convertView.findViewById(R.id.JobNum); // jobID
        holder.lineitems = (ListView)convertView.findViewById(R.id.list); // lineitems

        convertView.setTag(holder);
    } else
        holder = (ViewHolder) convertView.getTag();

    holder.jobnum.setText(job.getJobID());
    listviewadapter = new LineItemCustomListViewAdapter(context,R.layout.list_row, job.getLineItem());
    holder.lineitems.setAdapter(listviewadapter);   

    return convertView;
}

This is working fine upto the point of displaying the outer job list and the inner list too. But each job internally is only showing the first product item, i.e each row of the outer list only shows the first row of the inner list.

Can anyone point out if I'm missing something or where I'm going wrong. Any help will be greatly appreciated!

edit: As per Barend's comment, used ExpandableListAdapter to get this to work.

Since ExpandableListView adds each element as just a new row in parent/child groups as necessary, the dynamic nature of lists didn't matter. I stored the parent and its associated children data in ArrayList objects which are being handled in the extended adapter class.

public class ExpandableAdapter extends BaseExpandableListAdapter {

    private Context context;
    private ArrayList<String> parent;
    private ArrayList<ArrayList<LineItem>> children;

    public ExpandableAdapter(Context context, ArrayList<String> parent,
        ArrayList<ArrayList<LineItem>> children) {
         this.context = context;
         this.parent = parent;
         this.children = children;
    }

    @Override
    public View getChildView(final int groupPosition, final int childPosition,
        boolean isLastChild, View convertView, ViewGroup parent) {

        final LineItem lineitem = (LineItem)getChild(groupPosition, childPosition);

        if (convertView == null) {
            LayoutInflater mInflater = (LayoutInflater) context
                .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
               convertView = mInflater.inflate(R.layout.list_row, null);
        }

        TextView item; // item
        TextView desc; // desc

        item = (TextView)convertView.findViewById(R.id.Item); // item
        desc = (TextView)convertView.findViewById(R.id.Desc); // desc

        item.setText(lineitem.getItem());
        desc.setText(lineitem.getDesc());
        return convertView;
    }


    public View getGroupView(int groupPosition, boolean isExpanded,
        View convertView, ViewGroup parent) {
    Integer parentnum = Integer.valueOf(groupPosition);

        String parentcond = (String) getGroup(groupPosition);
        TextView jobnum; // jobID
        TextView cond; 

        if (convertView == null) {
            LayoutInflater infalInflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = infalInflater.inflate(R.layout.list_job,
                null);
        }    
        jobnum = (TextView)convertView.findViewById(R.id.JobNum); // jobID
        cond = (TextView)convertView.findViewById(R.id.Condition); // cond

        jobnum.setText(parentnum.toString())
        cond.setText(parentcond);
        return convertView;
   }

   /// other methods
} 

Upvotes: 3

Views: 10199

Answers (2)

user3510029
user3510029

Reputation: 21

You'd better not nest ListView. This way is inefficient.

You can use ExpandableListView. Or you can use the project PreOrderTreeAdapter. It matches your case and is easy to use.

Upvotes: 0

Barend
Barend

Reputation: 17419

You shouldn't try to nest two list views – both are scrolling views and the UX becomes horrible. What you should do instead is use ExpandableListAdapter, which lets you make a list of parent (group) and child views. It's possible to have multiple children per group, so in practice, you have nested lists, but in reality, it's a single ListView.

Upvotes: 9

Related Questions