ListView recycling with multiple types of views

2020-07-30 17:42发布

问题:

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?

回答1:

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;
  }


回答2:

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.



回答3:

What about using a HeaderView and a FooterView on the ListView ?

That way, you haven't to handle multiple types...