1

我制作了一个聊天应用程序,其中聊天视图由许多行组成,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除了使用的 Drawable 之外,这两个布局chat_msg_row是相同的,其中一个使用白色图像,另一个使用蓝色图像。

4

2 回答 2

2

我最近遇到了类似的问题。我所做的是删除

if (convertView == null) 

并返回视图本身。上面的代码所做的是:它检查当前列表中是否存在先前的缓存。如果存在,它会重新使用以前存在的列表。希望能帮助到你

于 2013-06-17T11:32:25.900 回答
1

由于您没有使用适配器的getItemViewType和方法,因此将假定您只有一种类型的行(尽管您实际上使用了两种类型),并且会在行出现在列表中时对其进行回收。所以,如果不是,你会得到一个回收的行,它可能是这两种类型中的一种,具体取决于它的位置。getViewTypeCountListViewconvertViewnull

但是只有当你的行真的不同(额外的小部件、放置规则等)时,才应该实施上述方法。如果您的两行仅在背景图像上有所不同,那么您只需要一行,您将根据应用程序的逻辑设置背景,如下所示:

//...
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);
}
// ...
于 2012-11-01T08:10:16.607 回答