我制作了一个聊天应用程序,其中聊天视图由ListView
中的许多行组成,其中用户发送的消息以白色显示,而朋友收到的消息以蓝色显示。
这种行为很好,但是当我在变得非常大(例如30行)之后滚动列表时,颜色会混乱。我为每一行使用不同的布局,白色行布局和蓝色行布局。
当我在列表中上下滚动多次时,颜色会随机切换(即我的一些消息为蓝色,其他消息为白色,另一端(与我聊天的朋友)变为白色和其他消息随机变成蓝色。
我会给你一个关于所用代码的剪辑预览:
这是我的自定义适配器中的getView
方法,它扩展了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;
}
两种布局chat_msg_row2
和chat_msg_row
除了使用的Drawable外是相同的,其中一个使用白色图像而另一个使用蓝色图像。
答案 0 :(得分:2)
我最近遇到了类似的问题。我做的是删除
if (convertView == null)
并返回View本身。上面代码的作用是:它检查当前列表中是否存在先前的缓存。如果存在,则重新使用先前存在的列表。希望它有所帮助
答案 1 :(得分:1)
由于您没有使用适配器的getItemViewType
和getViewTypeCount
方法,因此ListView
将假设您只有一种类型的行(尽管您实际使用了两种类型)并将回收列表中显示的行。因此,当convertView
不是null
时,您会得到一个循环行,可能是这两种类型中的一种,具体取决于其位置。
但是只有当你的行真的不同时(额外的小部件,放置规则等),才能实现上述方法。如果您的两行不同仅由背景图片,那么您只需要一行,并且您将根据应用的逻辑设置背景,如下所示:
//...
if (convertView == null) {
holder = new ViewHolder();
// just inflate one of the rows if they are identical
convertView = mInflater.inflate(R.layout.chat_msg_row, parent, false);
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();
}
// set the background image as desired
if(from.toString().toLowerCase().equals("me")){
// I assumed you set the background on the root of the View row, convertView
// otherwise search for the desired view in convertView and set the background
convertView.setBackgroundResource(R.drawable.the_me_background_drawable);
} else {
convertView.setBackgroundResource(R.drawable.the_other_user_background_drawable);
}
// ...