I have made a chat application where the chat view is formed from many rows in a ListView where messages sent by the user are displaying in white and messages received by friend are displayed in blue.
This behavior works fine, but when I scroll the list after becoming really big (e.g. 30 rows) the colors are messed. I use different layouts for each row, white row layout and blue row layout.
When I scroll multiple times up and down the list the colors keeps switching randomly (i.e. some of my messages are in blue and others in white, and some of the other end (the friend chatting with me) becomes white and other messages become blue in a random way.
I’ll give you a snipped preview on the code used:
This is the getView method in my custom adapter which extends BaseAdapter:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
final int pos = position;
String from = messages.get(pos).getFrom();
if (convertView == null) {
holder = new ViewHolder();
// If message is sent by me (the user)
if(from.toString().toLowerCase().equals("me")){
convertView = mInflater.inflate(R.layout.chat_msg_row2, null);
}
// if message is sent by his friend (the other end user)
else{
convertView = mInflater.inflate(R.layout.chat_msg_row, null);
}
holder.userName = (TextView) convertView.findViewById(R.id.msgusername);
holder.userImage = (ImageView) convertView.findViewById(R.id.ppic);
holder.date = (TextView) convertView.findViewById(R.id.msgdate);
holder.text = (TextView) convertView.findViewById(R.id.msg);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.userName.setText( messages.get(pos).getFrom() );
holder.text.setText( messages.get(pos).getText() );
holder.date.setText( messages.get(pos).getDate() );
String img = messages.get(pos).getImage();
if(img.substring(0,4).equalsIgnoreCase("http") ){
try{
ImageLoader imloader = new ImageLoader( ChatActivity.this );
holder.userImage.setTag(img);
imloader.DisplayImage( img, ChatActivity.this , holder.userImage );
}
catch(Exception e){
e.printStackTrace();
}
}
return convertView;
}
public long getItemId(int position){
return 1;
}
public class ViewHolder{
TextView userName;
ImageView userImage;
TextView text;
TextView date;
}
The two layouts, chat_msg_row2 and chat_msg_row, are identical except for the Drawable used, where one is using a white image and the other using a blue image.
As you didn’t use the
getItemViewTypeand thegetViewTypeCountmethods of the adapter, then theListViewwill assume you only have one type of row(although you actually use two types) and will recycle rows as they appear in the list. So, when theconvertViewis notnullyou get a recycled row that could be either one of those two types depending on its position.But the methods above should be implemented only if your rows are really different(extra widgets, placement rules etc). If your two rows are different only by the background image then you need only one row and you’ll be setting the background based on your app’s logic, something like this: