8

I have a ListAdapter with a lot of different layouts for the rows. To have a clean code I want to outsource the layouts for the rows from the getView() of the adapter in View classes. Is it possible to inflate a XML layout into a custom view? I've only found the LayoutInflater but it returns a View and that does not help. I want to have something like the setLayout() of an Activity. Is this possible?

Thanks!

dbrettschneider
  • 3,173
  • 1
  • 29
  • 28

2 Answers2

28

You can have a custom row view and inflate your xml in its constructor:

public MyRow extends LinearLayout {
    public MyRow(Context context) {
        super(context);
        LayoutInflater.from(context).inflate(R.layout.my_row, this, true);
          ... other initialization ...
    }
}

and then use merge in my_row.xml:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
  ... your row layout ...
</merge>

The merge element causes its children to be added as children of your custom view. Check out Merging Layouts for more info.

Matthew
  • 44,826
  • 10
  • 98
  • 87
  • I tried this and got error `merge can be used only with a valid view group root and attachtoroot=true`. Why? I'm using exatcly the same call, I'm using an xml with merge as a root, with no attributes. – Frederic Blase Dec 25 '12 at 12:55
  • 1
    that link is a 404 now. the closest I could find was http://developer.android.com/training/improving-layouts/reusing-layouts.html but I'd also suggest reading http://android-developers.blogspot.ca/2009/03/android-layout-tricks-3-optimize-by.html – Chani Nov 29 '13 at 18:41
0

I alwas use a custom Adapter with a viewholder like:

public class CalendarAdapter extends BaseAdapter {
protected static CalViewHolder holder;
private LayoutInflater mInflater;
public HashMap<Integer,String[]> appointments = new HashMap<Integer,String[]>();

public CalendarAdapter(Context context,HashMap<Integer,String[]> set_appointments) {
    // Cache the LayoutInf
     mInflater = LayoutInflater.from(context);
     appointments = set_appointments;
}
@Override
public int getCount() {
    // TODO Auto-generated method stub
    return appointments == null ? 0:appointments.size();
}
@Override
public Object getItem(int arg0) {
    // TODO Auto-generated method stub
    return null;
}
@Override
public long getItemId(int arg0) {
    // TODO Auto-generated method stub
    return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
     if (convertView == null) {
         convertView = mInflater.inflate(R.xml.appointment, null);
         holder = new CalViewHolder();
         holder.app_lay = (LinearLayout) convertView.findViewById(R.id.appointment_layout);
         holder.app_head = (TextView) convertView.findViewById(R.id.appointment_head);
         holder.app_body = (TextView) convertView.findViewById(R.id.appointment_body);
         convertView.setTag(holder);
     }else{
        holder = (CalViewHolder) convertView.getTag();
     }
     holder.app_head.setText(appointments.get(position)[0]);
     holder.app_body.setText(appointments.get(position)[1]);
     return convertView;
}

static class CalViewHolder {
    LinearLayout app_lay;
    TextView app_head;
    TextView app_body; 
}

}

Macarse
  • 91,829
  • 44
  • 175
  • 230
2red13
  • 11,197
  • 8
  • 40
  • 52
  • I use this method too, but I have a lot of different layouts for the row, so there is a really big "if else". – dbrettschneider Apr 04 '11 at 07:12
  • with many different layouts, the performance will slow down, I realised a similar Listview with up to six different holders, this is acceptable, but keep in mind, that you have to reload every single item, if you add or remove controls. Perhaps a listview is not really what you need, think about adding your views simply to a LinearLayout. – 2red13 Apr 04 '11 at 07:27