简体   繁体   中英

Why my listview adapter doesn't show the right layout on new view?

I have a custom Cursor Adapter that is based off of the MMS and SMS database in android. code looks like this as follows:

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {

    Message m = Message.getMessage(context, cursor); // gets message from cursor
    int t = m.getType(); // this gets the type of message it is .. 2 = recv, 1 = sent

    switch(t){
    case Message.MMS_IN: // 128
        return mInflater.inflate(R.layout.messagelist_item_recv, parent, false);
    case Message.MMS_OUT: // 132
        return mInflater.inflate(R.layout.messagelist_item_sent, parent, false);
    case Message.SMS_IN: // 2
        return mInflater.inflate(R.layout.messagelist_item_recv, parent, false);
    case Message.SMS_OUT: // 1
        return mInflater.inflate(R.layout.messagelist_item_sent, parent, false);
    default:
        return null;
    }
}

The R.layout.messagelist_item_sent is for sent messages and the R.layout.messagelist_item_recv is for received messages. But looking at my messages, the rows that are first shown when the listview are shown correctly, but when I go up the listview to new views, the layouts are mixed up. The recv layout is where the sent layout is supposed to be and vice versa. Any one know why this kind of problem would be occuring?

* EDIT **

@Override
public int getItemViewType(int position) {
     // move the cursor to the position
Cursor c = (Cursor)getItem(position);
Message m = Message.getMessage(context, c);

if (isInbox(m.getType())){
   inflater.inflate(recv view);
 // it's been shortened 
} else {
   inflater.inflate(send view);   
// and determine the correct type of row layout
     // return 0 or 1
     // use the code that you currently have from the newView method
}

But looking at my messages, the rows that are first shown when the listview are shown correctly, but when I go up the listview to new views, the layouts are mixed up.

That is probably happening because you don't handle the ListView recycling mechanism right. The newView method is not called for each row, it's called when there isn't a recycled view to be used for the row layout(like when the ListView is first shown, that's why the rows appear in the correct order). Otherwise, the ListView will use a recycled view which may or may not be the right type of view.

You should use the methods getViewTypeCount() and getItemViewType() . The method getViewTypeCount() will return two(as you have two types of rows?!?) and then implement the logic to determine the correct row type in the getItemViewType :

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
     Cursor c = (Cursor)getItem(position);
     Message m = Message.getMessage(context, c);
     switch(m.getType()){
         case Message.MMS_IN: // 128
             return 1;
         case Message.MMS_OUT: // 132
             return 0;
         case Message.SMS_IN: // 2
             return 1;
         case Message.SMS_OUT: // 1
             return 0;
         default:
             return 0;
      }
}

Then in the newView method:

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    int rowType = getItemViewType(cursor.getPosition());
    if (rowType == 0){
        return mInflater.inflate(R.layout.messagelist_item_sent, parent, false);
    } else if (rowType == 1){    
        return mInflater.inflate(R.layout.messagelist_item_recv, parent, false);
    } else {
        return null;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM