My problem is that I don\'t know whether I should use multiple list view or a custom listview item adapter which can grows dynamically. For example, for a particular user, t
Here's an idea that'll probably enable you to introduce as many item types as you like without having to modify adapter every time you do:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
AbstractItem abstractItem = ((AbstractItem)getItem(position));
// if null or new item type is different than the one already there
if (convertView == null || (convertView.getTag() != null
&& ((AbstractItem)convertView.getTag()).getType().equals(abstractItem.getType())) {
convertView = abstractItem.inflateSelf(getContext());
}
abstractItem.fillViewWithData(convertView);
convertView.setTag(abstractItem);
return convertView;
}
public class AbstractItem {
public abstract View inflateSelf(Context context);
public abstract String getType();
public abstract void fillViewWithData(View view);
}
public class PictureSnapItem extends AbstractItem {
// data fields
WeakReference<Bitmap> wBitmap;
String pictureComment;
...
public abstract View inflateSelf(Context context) {
// get layout inflater, inflate a layout resource, return
return ((Activity)context).getLayoutInflater.inflate(R.layout.picture_snap_item);
}
public abstract String getType() {
// return something class-specific, like this
return getClass().getCanonicalName();
}
public abstract void fillViewWithData(View view) {
// fill the view with data from fields, assuming view has been
// inflated by this very class's inflateSelf(), maybe throw exception if
// required views can't be found
ImageView img = (ImageView) view.findViewById(R.id.picture);
TextView comment = (TextView) view.findViewById(R.id.picture_comment)
}
}
... and then extend AbstractItem and add instances to adapter, no need to add any if clauses to getView() any more.
If you have small number of possible variants (on your screenshots I can see 2 different list items) You have two possible variants:
Setup count of different types by this method, and provide type for every item - and you can use convertView.
Create "full" list item view and set visibility for elements, that you don't want to see in particular item.
Some code for #2:
public class ListTestActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
List<Element> list = new ArrayList<Element>();
list.add(new Element(0));
list.add(new Element(0));
list.add(new Element(1));
list.add(new Element(0));
list.add(new Element(1));
list.add(new Element(1));
list.add(new Element(0));
list.add(new Element(0));
list.add(new Element(1));
list.add(new Element(1));
list.add(new Element(1));
list.add(new Element(0));
list.add(new Element(0));
list.add(new Element(1));
list.add(new Element(0));
list.add(new Element(0));
((ListView) findViewById(android.R.id.list)).setAdapter(new SampleAdapter(this, list));
}
private class SampleAdapter extends BaseAdapter {
private List<Element> list;
private Context context;
public SampleAdapter(Context context, List<Element> list) {
this.list = list;
this.context = context;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Element getItem(int position) {
return list.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
switch (getItemViewType(position)) {
case 0:
convertView = new CheckBox(context);
break;
default:
convertView = new Button(context);
break;
}
// Output here shows that you can lay on getItemViewType(position) as indicator of convertView type or structure
Log.e("test", getItemViewType(position) + ": " + convertView.getClass().getSimpleName());
return convertView;
}
@Override
public int getItemViewType(int position) {
return getItem(position).type;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public long getItemId(int position) {
return position;
}
}
private class Element {
public int type;
public Element(int type) {
this.type = type;
}
}
}
A custom adapter would solve your problem. This is because you can change the views that are being added to each row in the Listview, because you can change the content via logic that you implement in the custom adapter.
When the getView() method returns a view that is not null, this means for that particular row there is a view that was already there. As such if this is the case, you may or may not want to change content in that specific view. Or you could build a brand new view with dynamic content for that particular row.
One thing to note is that getView() will be called as many times as there are items found in your adapter.