I'm currently working on a quite simply ListView with up to 2 different view types. In order too make everything smooth i try to recycle views. My code is by now:
@Override
public int getItemViewType (int position){
if(mHasBefore&&position==0){
return TYPE_PAGER;
}else if(mHasNext&&position==getCount()-1){
return TYPE_PAGER;
}else return TYPE_SCORE;
}
@Override
public int getViewTypeCount (){
return 1+((mHasBefore==true||mHasNext==true)?1:0);
}@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.d("outa","View: pos: "+position+ " . "+getItemViewType(position)+" - "+getViewTypeCount());
if(getItemViewType(position)==TYPE_SCORE)return getScoreView(position,convertView,parent);
else return getPagerView(position,convertView,parent);
}
protected View getPagerView(int position,View convertView,ViewGroup parent){
if (convertView == null){
convertView = LayoutInflater.from(parent.getContext()).inflate(
R.layout.listitem_highscore_pager, null);}}
protected View getScoreView(int position,View convertView,ViewGroup parent){
if (convertView == null){
convertView = LayoutInflater.from(parent.getContext()).inflate(
R.layout.listitem_highscore, null);}}
Basicly it should show a different view on the last item but it still shows the default item even if the LogCat states it is not TYPE_SCORE in getView(). Hence convertView does provide a recycled view. Do I do something wrong or is this a normal behaviour?
Here you go:
private static final int TYPE_PAGER = 0;
private static final int TYPE_PAGER = 1;
private static final int VIEW_COUNT = 2;
private LayoutInflater mInflater = LayoutInflater.from(context);
@Override
public int getViewTypeCount (){
return VIEW_COUNT;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
ViewHolder2 holder2;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
holder2 = new ViewHolder2();
switch(type){
case TYPE_SCORE:
Log.i(TAG, "ConvertView type1");
convertView = mInflater.inflate(R.layout.listitem_highscore, null);
convertView.setTag(R.layout.listitem_highscore, holder);
break;
case TYPE_PAGER:
Log.i(TAG, "ConvertView type0");
convertView = mInflater.inflate(R.layout.listitem_highscore_pager, null);
convertView.setTag(R.layout.listitem_highscore_pager, holder2);
break;
}
}
} else{
// Get the ViewHolder back to get fast access to the TextViews
holder = (ViewHolder) convertView.getTag(R.layout.baseadapter);
holder2 = (ViewHolder2)convertView.getTag(R.layout.baseadapter1);
}
switch(type){
case TYPE_SCORE:
holder.holderText.setText("type1");
break;
case TYPE_PAGER:
holder2.holder2Text.setText("type2");
break;
}
}
View holders:
static class ViewHolder {
//Place your views here for example:
TextView holderText;
}
static class ViewHolder2{
TextView holder2Text;
}
getItemViewType()
has to return stable values. IOW, for position
of 0
, getItemViewType()
has to always return TYPE_PAGER
, not based on some other mHasBefore
value.
If you wish to have unstable values, you will need to call notifyDataSetChanged()
every time you would need to change the value. IOW, if you toggle mHasBefore
from whatever it was originally, you would need to call notifyDataSetChanged()
, and again if you change mHasBefore
back to its original value.
What about using a HeaderView and a FooterView on the ListView ?
That way, you haven't to handle multiple types...