Andy Joyce
Andy Joyce

Reputation: 2832

Listview with two xml's changing when scrolling

At the moment i'm working on a messaging page for my application. The problem is that i use two different xml's within a list view. Now i can get the data to display on the page in the correct order, however, when i scroll the data still appears in the correct order but in a different style. For example before scrolling the last message would use the messagesent.xml if i scroll up then scroll down that same message now has the message.xml style. The code i'm currently using is below.

public class MessagingAdapter extends ArrayAdapter<MessagingObject> {


private static final String userID = "USERID";
private static final int TYPE_ITEM1 = 0;
private static final int TYPE_ITEM2 = 1;

public String newid;
public Context context;
public ArrayList<MessagingObject> object = new ArrayList<MessagingObject>();

int type;

public MessagingAdapter(Context context, int textViewResourceId, ArrayList<MessagingObject> objects) {
    super(context, textViewResourceId, objects);
    this.context = context;
    this.object = objects;
}

@Override
public int getItemViewType(int position) {

    if (userID.equals(newid)) {
        type = TYPE_ITEM1;
    } else {
        type = TYPE_ITEM2;
    }
    return type;
}

@Override
public int getViewTypeCount() {

    return 2;
}

@Override
public View getView(int position, View convertview, ViewGroup parent) {


    MessagingObject i = object.get(position);
    newid = i.getMessageID();

    LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertview = inflater.inflate(R.layout.messagesright_layout, null);

    if (convertview == null) {
        convertview = inflater.inflate(R.layout.messagesright_layout, null);
    }

    if (type == TYPE_ITEM1) {
       convertview = inflater.inflate(R.layout.messagesright_layout, null);
       TextView sentmessage = (TextView) convertview.findViewById(R.id.messagesent_text);
       sentmessage.setText(object.get(position).getMessage());

       TextView senttime = (TextView) convertview.findViewById(R.id.messagesentTime);
       String senttimestring = new String().valueOf(object.get(position).getTimeStamp());
       senttime.setText(senttimestring);

      } else {
       convertview = inflater.inflate(R.layout.messages_layout, null);
       TextView message = (TextView) convertview.findViewById(R.id.message_text);
       message.setText(object.get(position).getMessage());

       TextView time = (TextView) convertview.findViewById(R.id.messageTime);
       String timestring = new String().valueOf(object.get(position).getTimeStamp());
       time.setText(timestring);
     }
    return convertview;
}

Now i understand this is to do with Listview Recycling, however, i've tried some solutions i've found on other stack overflow posts with no luck, and i haven't been able to find many that cover this problem with 2 xmls.

Thanks for having a look!

Upvotes: 2

Views: 127

Answers (3)

Blackbelt
Blackbelt

Reputation: 157457

your getView is wrong. You should ask the type at the position and inflate the view only if the convertView is null.

@Override
public View getView(int position, View convertview, ViewGroup parent) {


MessagingObject i = object.get(position);
newid = i.getMessageID();
int type = getItemViewType(position);

if (convertview == null) {
    LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (type == TYPE_ITEM1) {
       convertview = inflater.inflate(R.layout.messagesright_layout, null);
    } else if (type == TYPE_ITEM2) {
       convertview = inflater.inflate(R.layout.messages_layout, null);
    }
}

if (type == TYPE_ITEM1) {
   TextView sentmessage = (TextView) convertview.findViewById(R.id.messagesent_text);
   sentmessage.setText(object.get(position).getMessage());

   TextView senttime = (TextView) convertview.findViewById(R.id.messagesentTime);
   String senttimestring = new String().valueOf(object.get(position).getTimeStamp());
   senttime.setText(senttimestring);

  } else {

   TextView message = (TextView) convertview.findViewById(R.id.message_text);
   message.setText(object.get(position).getMessage());

   TextView time = (TextView) convertview.findViewById(R.id.messageTime);
   String timestring = new String().valueOf(object.get(position).getTimeStamp());
   time.setText(timestring);
 }
return convertview;
}

Upvotes: 2

se22as
se22as

Reputation: 2382

I have coded a list which has 2 xml's for the layouts of the different rows in a list and I have not seen this issue.

I don't store the view type in a local variable, instead I always call "getItemViewType" at the beginning of "getView" so I am guaranteed to get the correct view type for the current position, see my tweaks to your code below (I have not checked this compiles)


public class MessagingAdapter extends ArrayAdapter<MessagingObject> {


private static final String userID = "USERID";
private static final int TYPE_ITEM1 = 0;
private static final int TYPE_ITEM2 = 1;

public String newid;
public Context context;
public ArrayList<MessagingObject> object = new ArrayList<MessagingObject>();

int type;

public MessagingAdapter(Context context, int textViewResourceId, ArrayList<MessagingObject> objects) {
    super(context, textViewResourceId, objects);
    this.context = context;
    this.object = objects;
}

@Override
public int getItemViewType(int position) {

    if (userID.equals(newid)) {
        return = TYPE_ITEM1;
    } else {
        return = TYPE_ITEM2;
    }
}

@Override
public int getViewTypeCount() {

    return 2;
}

@Override
public View getView(int position, View convertview, ViewGroup parent) {


    MessagingObject i = object.get(position);
    newid = i.getMessageID();

    LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if (getItemViewType(position) == TYPE_ITEM1) {
       convertview = inflater.inflate(R.layout.messagesright_layout, null);
       TextView sentmessage = (TextView) convertview.findViewById(R.id.messagesent_text);
       sentmessage.setText(object.get(position).getMessage());

       TextView senttime = (TextView) convertview.findViewById(R.id.messagesentTime);
       String senttimestring = new String().valueOf(object.get(position).getTimeStamp());
       senttime.setText(senttimestring);

      } else {
       convertview = inflater.inflate(R.layout.messages_layout, null);
       TextView message = (TextView) convertview.findViewById(R.id.message_text);
       message.setText(object.get(position).getMessage());

       TextView time = (TextView) convertview.findViewById(R.id.messageTime);
       String timestring = new String().valueOf(object.get(position).getTimeStamp());
       time.setText(timestring);
     }
    return convertview;

Upvotes: 2

Dhwanik Gandhi
Dhwanik Gandhi

Reputation: 685

try this:

if (convertview == null) {

if (type == TYPE_ITEM1) {
   convertview = inflater.inflate(R.layout.messagesright_layout, null);
   TextView sentmessage = (TextView) convertview.findViewById(R.id.messagesent_text);
   sentmessage.setText(object.get(position).getMessage());

   TextView senttime = (TextView) convertview.findViewById(R.id.messagesentTime);
   String senttimestring = new String().valueOf(object.get(position).getTimeStamp());
   senttime.setText(senttimestring);

  } else {
   convertview = inflater.inflate(R.layout.messages_layout, null);
   TextView message = (TextView) convertview.findViewById(R.id.message_text);
   message.setText(object.get(position).getMessage());

   TextView time = (TextView) convertview.findViewById(R.id.messageTime);
   String timestring = new String().valueOf(object.get(position).getTimeStamp());
   time.setText(timestring);
 }

Upvotes: 0

Related Questions