繁体   English   中英

Listview奇怪的滚动行为

[英]Listview strange behavior on scroll

我有一个listview(聊天)。 我得到一些奇怪的行为。 它发生在我向上滚动,然后一些项目开始搞乱,当我回到底部时,项目也搞砸了。 我唯一能想到的是每次滚动都会调用我的getView几次。 有谁知道我怎么能解决这个问题?

我看到这篇文章: 自定义ListView适配器,奇怪的ImageView行为,但他没有在创建后添加项目到列表。


<?xml version="1.0" encoding="utf-8"?>

<TextView
    android:id="@+id/right_message"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_toLeftOf="@+id/right_profilePic"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="5dp"
    android:layout_marginTop="20dp"
    android:autoLink="all"
    />


 <ImageView
     android:id="@+id/left_profilePic"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentBottom="true"
     android:layout_alignParentLeft="true"
     />

 <TextView
     android:id="@+id/left_message"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentBottom="true"
     android:layout_toRightOf="@+id/left_profilePic"
     android:layout_marginLeft="5dp"
     android:layout_marginRight="5dp"
     android:layout_marginTop="20dp"
     android:autoLink="all" 
     />

 <ImageView
     android:id="@+id/right_profilePic"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentBottom="true"
     android:layout_alignParentRight="true" 
     />

 <TextView
     android:id="@+id/left_time"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentTop="true"
     android:layout_marginLeft="70dp"
     android:layout_toRightOf="@+id/left_profilePic"
     android:textColor="@color/Gray" 
     />

 <TextView
     android:id="@+id/right_time"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentTop="true"
     android:layout_marginRight="70dp"
     android:layout_toLeftOf="@+id/right_profilePic"
     android:textColor="@color/Gray" 
     />

 <ImageView
     android:id="@+id/left_image_message"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentBottom="true"
     android:layout_toRightOf="@+id/left_profilePic"
     android:layout_marginLeft="5dp"
     android:layout_marginRight="5dp"
     android:layout_marginTop="20dp"
     />

 <ImageView
     android:id="@+id/right_image_message"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_alignParentBottom="true"
     android:layout_toLeftOf="@+id/right_profilePic"
     android:layout_marginLeft="5dp"
     android:layout_marginRight="5dp"
     android:layout_marginTop="20dp"
     />


更新

我必须在聊天中加载图片和谷歌静态地图,我想这对于列表视图来说很重要。

这是getView方法:

   public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
       Log.d("getView", "getview called");
       ViewHolder holder;
       if(convertView==null)
    {
        holder = new ViewHolder();
        convertView = inflater.inflate(R.layout.chat_item, null);

        holder.right_profilePic = (ImageView)     convertView.findViewById(R.id.right_profilePic);
        holder.right_message = (TextView) convertView.findViewById(R.id.right_message);
        holder.left_profilePic = (ImageView) convertView.findViewById(R.id.left_profilePic);
        holder.left_message = (TextView) convertView.findViewById(R.id.left_message);
        holder.right_time = (TextView) convertView.findViewById(R.id.right_time);
        holder.left_time = (TextView) convertView.findViewById(R.id.left_time);
        holder.right_image_message = (ImageView) convertView.findViewById(R.id.right_image_message);
        holder.left_image_message = (ImageView) convertView.findViewById(R.id.left_image_message);


        convertView.setTag(holder);
    }
    else
        holder=(ViewHolder)convertView.getTag();

    ChatItemBean bean = (ChatItemBean) chatItemList.get(position);
    Log.d("holder", bean.getId() + " | " + GlobalData.myId);
    if (bean.getId().equals(GlobalData.myId)) {
        Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.right_profilePic);
        if (bean.getType().equals("1")) {
            Picasso.with(context).load(init_link + bean.getMessage()).into(holder.right_image_message);
            holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
            //holder.right_image_message.setPadding(0, 0, 0, 20);
        } else if (bean.getType().equals("2")) {
            StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
            String first = tokens.nextToken();
            String second = tokens.nextToken();
            String url = "http://maps.google.com/maps/api/staticmap?center=" + 
                            first + "," + second + "&zoom=15&size=200x200&sensor=false";
            Picasso.with(context).load(url).into(holder.right_image_message);
            holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
        } else {
            holder.right_message.setText(bean.getMessage());
            holder.right_message.setBackgroundResource(R.drawable.chat_background_right);
            }
        holder.right_time.setText(bean.getTime());
    } else {
        Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.left_profilePic);

        if (bean.getType().equals("1")) { 
            Picasso.with(context).load(init_link + bean.getMessage()).into(holder.left_image_message);
            holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
            holder.left_image_message.setPadding(0, 10, 0, 30);

        } else if (bean.getType().equals("2")) {
            StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
            String first = tokens.nextToken();
            String second = tokens.nextToken();
            String url = "http://maps.google.com/maps/api/staticmap?center=" + 
                            first + "," + second + "&zoom=15&size=200x200&sensor=false";
            Picasso.with(context).load(url).into(holder.left_image_message);
            holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
        } else {
            holder.left_message.setText(bean.getMessage());
            holder.left_message.setBackgroundResource(R.drawable.chat_background_left);
        }

        holder.left_time.setText(bean.getTime());
    }
    return convertView;
}public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    Log.d("getView", "getview called");
    ViewHolder holder;
    if(convertView==null)
    {
        holder = new ViewHolder();
        convertView = inflater.inflate(R.layout.chat_item, null);

        holder.right_profilePic = (ImageView) convertView.findViewById(R.id.right_profilePic);
        holder.right_message = (TextView) convertView.findViewById(R.id.right_message);
        holder.left_profilePic = (ImageView) convertView.findViewById(R.id.left_profilePic);
        holder.left_message = (TextView) convertView.findViewById(R.id.left_message);
        holder.right_time = (TextView) convertView.findViewById(R.id.right_time);
        holder.left_time = (TextView) convertView.findViewById(R.id.left_time);
        holder.right_image_message = (ImageView) convertView.findViewById(R.id.right_image_message);
        holder.left_image_message = (ImageView) convertView.findViewById(R.id.left_image_message);


        convertView.setTag(holder);
    }
    else
        holder=(ViewHolder)convertView.getTag();

    ChatItemBean bean = (ChatItemBean) chatItemList.get(position);
    Log.d("holder", bean.getId() + " | " + GlobalData.myId);
    if (bean.getId().equals(GlobalData.myId)) {
        Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.right_profilePic);
        if (bean.getType().equals("1")) {
            Picasso.with(context).load(init_link + bean.getMessage()).into(holder.right_image_message);
            holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
            //holder.right_image_message.setPadding(0, 0, 0, 20);
        } else if (bean.getType().equals("2")) {
            StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
            String first = tokens.nextToken();
            String second = tokens.nextToken();
            String url = "http://maps.google.com/maps/api/staticmap?center=" + 
                            first + "," + second + "&zoom=15&size=200x200&sensor=false";
            Picasso.with(context).load(url).into(holder.right_image_message);
            holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
        } else {
            holder.right_message.setText(bean.getMessage());
            holder.right_message.setBackgroundResource(R.drawable.chat_background_right);
            }
        holder.right_time.setText(bean.getTime());
    } else {
        Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.left_profilePic);

        if (bean.getType().equals("1")) { 
            Picasso.with(context).load(init_link + bean.getMessage()).into(holder.left_image_message);
            holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
            holder.left_image_message.setPadding(0, 10, 0, 30);

        } else if (bean.getType().equals("2")) {
            StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
            String first = tokens.nextToken();
            String second = tokens.nextToken();
            String url = "http://maps.google.com/maps/api/staticmap?center=" + 
                            first + "," + second + "&zoom=15&size=200x200&sensor=false";
            Picasso.with(context).load(url).into(holder.left_image_message);
            holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
        } else {
            holder.left_message.setText(bean.getMessage());
            holder.left_message.setBackgroundResource(R.drawable.chat_background_left);
        }

        holder.left_time.setText(bean.getTime());
    }
    return convertView;
}

public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    Log.d("getView", "getview called");
    ViewHolder holder;
    if(convertView==null)
    {
        holder = new ViewHolder();
        convertView = inflater.inflate(R.layout.chat_item, null);

        holder.right_profilePic = (ImageView) convertView.findViewById(R.id.right_profilePic);
        holder.right_message = (TextView) convertView.findViewById(R.id.right_message);
        holder.left_profilePic = (ImageView) convertView.findViewById(R.id.left_profilePic);
        holder.left_message = (TextView) convertView.findViewById(R.id.left_message);
        holder.right_time = (TextView) convertView.findViewById(R.id.right_time);
        holder.left_time = (TextView) convertView.findViewById(R.id.left_time);
        holder.right_image_message = (ImageView) convertView.findViewById(R.id.right_image_message);
        holder.left_image_message = (ImageView) convertView.findViewById(R.id.left_image_message);


        convertView.setTag(holder);
    }
    else
        holder=(ViewHolder)convertView.getTag();

    ChatItemBean bean = (ChatItemBean) chatItemList.get(position);
    Log.d("holder", bean.getId() + " | " + GlobalData.myId);
    if (bean.getId().equals(GlobalData.myId)) {
        Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.right_profilePic);
        if (bean.getType().equals("1")) {
            Picasso.with(context).load(init_link + bean.getMessage()).into(holder.right_image_message);
            holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
            //holder.right_image_message.setPadding(0, 0, 0, 20);
        } else if (bean.getType().equals("2")) {
            StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
            String first = tokens.nextToken();
            String second = tokens.nextToken();
            String url = "http://maps.google.com/maps/api/staticmap?center=" + 
                            first + "," + second + "&zoom=15&size=200x200&sensor=false";
            Picasso.with(context).load(url).into(holder.right_image_message);
            holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
        } else {
            holder.right_message.setText(bean.getMessage());
            holder.right_message.setBackgroundResource(R.drawable.chat_background_right);
            }
        holder.right_time.setText(bean.getTime());
    } else {
        Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.left_profilePic);

        if (bean.getType().equals("1")) { 
            Picasso.with(context).load(init_link + bean.getMessage()).into(holder.left_image_message);
            holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
            holder.left_image_message.setPadding(0, 10, 0, 30);

        } else if (bean.getType().equals("2")) {
            StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
            String first = tokens.nextToken();
            String second = tokens.nextToken();
            String url = "http://maps.google.com/maps/api/staticmap?center=" + 
                            first + "," + second + "&zoom=15&size=200x200&sensor=false";
            Picasso.with(context).load(url).into(holder.left_image_message);
            holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
        } else {
            holder.left_message.setText(bean.getMessage());
            holder.left_message.setBackgroundResource(R.drawable.chat_background_left);
        }

        holder.left_time.setText(bean.getTime());
    }
    return convertView;
}

在此输入图像描述


更新

在这里,我尝试使用两种不同的布局:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    Log.d("getView", "getview called");
    ViewHolder holder;
    ChatItemBean checkBean = (ChatItemBean) chatItemList.get(position);

    if (checkBean.getId().equals(GlobalData.myId)) {
         if(convertView==null)
         {
             holder = new ViewHolder();
             convertView = inflater.inflate(R.layout.chat_item_right, null);
             holder.right_profilePic = (ImageView) convertView.findViewById(R.id.right_profilePic);
             holder.right_message = (TextView) convertView.findViewById(R.id.right_message);
             holder.right_time = (TextView) convertView.findViewById(R.id.right_time);
             holder.right_image_message = (ImageView) convertView.findViewById(R.id.right_image_message);
             convertView.setTag(holder);
         } else 
             holder=(ViewHolder)convertView.getTag();

         ChatItemBean bean = (ChatItemBean) chatItemList.get(position);
         Log.d("holder", bean.getId() + " | " + GlobalData.myId);

         Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.right_profilePic);
        if (bean.getType().equals("1")) {
            Picasso.with(context).load(init_link + bean.getMessage()).into(holder.right_image_message);
            holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
            //holder.right_image_message.setPadding(0, 0, 0, 20);
        } else if (bean.getType().equals("2")) {
            StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
            String first = tokens.nextToken();
            String second = tokens.nextToken();
            String url = "http://maps.google.com/maps/api/staticmap?center=" + 
                            first + "," + second + "&zoom=15&size=200x200&sensor=false";
            Picasso.with(context).load(url).into(holder.right_image_message);
            holder.right_image_message.setBackgroundResource(R.drawable.chat_background_right);
        } else {
            holder.right_message.setText(bean.getMessage());
            holder.right_message.setBackgroundResource(R.drawable.chat_background_right);
            }
        holder.right_time.setText(bean.getTime());

    } else {
        if(convertView==null)
        {
            holder = new ViewHolder();
            convertView = inflater.inflate(R.layout.chat_item, null);

            holder.left_profilePic = (ImageView) convertView.findViewById(R.id.left_profilePic);
            holder.left_message = (TextView) convertView.findViewById(R.id.left_message);
            holder.left_time = (TextView) convertView.findViewById(R.id.left_time);
            holder.left_image_message = (ImageView) convertView.findViewById(R.id.left_image_message);

            convertView.setTag(holder);
        }
        else
            holder=(ViewHolder)convertView.getTag();

        ChatItemBean bean = (ChatItemBean) chatItemList.get(position);
        Log.d("holder", bean.getId() + " | " + GlobalData.myId);

            Picasso.with(context).load(bean.getImage()).resize(130, 130).into(holder.left_profilePic);

            if (bean.getType().equals("1")) { 
                Picasso.with(context).load(init_link + bean.getMessage()).into(holder.left_image_message);
                holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
                holder.left_image_message.setPadding(0, 10, 0, 30);

            } else if (bean.getType().equals("2")) {
                StringTokenizer tokens = new StringTokenizer(bean.getMessage(), "&");
                String first = tokens.nextToken();
                String second = tokens.nextToken();
                String url = "http://maps.google.com/maps/api/staticmap?center=" + 
                                first + "," + second + "&zoom=15&size=200x200&sensor=false";
                Picasso.with(context).load(url).into(holder.left_image_message);
                holder.left_image_message.setBackgroundResource(R.drawable.chat_background_left);
            } else {
                holder.left_message.setText(bean.getMessage());
                holder.left_message.setBackgroundResource(R.drawable.chat_background_left);
            }

            holder.left_time.setText(bean.getTime());
    }

    return convertView;
}

但是当我滚动一点时,我的应用程序崩溃,就像它试图搞砸的那一刻,我得到的目标一定不能为空。 第124行使用毕加索加载配置文件。

12-01 21:14:40.442: E/AndroidRuntime(21764): java.lang.IllegalArgumentException: Target must not be null.
12-01 21:14:40.442: E/AndroidRuntime(21764):    at com.squareup.picasso.RequestCreator.into(RequestCreator.java:333)
12-01 21:14:40.442: E/AndroidRuntime(21764):    at com.squareup.picasso.RequestCreator.into(RequestCreator.java:319)
12-01 21:14:40.442: E/AndroidRuntime(21764):    at com.petcial.petopen.custom.ChatCustomAdapter.getView(ChatCustomAdapter.java:124)
  1. 对不同类型的列表项使用Seprate布局文件 -

使用两个布局文件最终会丢失一些convertView可重用性能的东西。 但是会帮助你拥有可以解决这个烂摊子的清洁用品。 确定哪个文件用于哪个项目。

2。 使用一个布局文件。

可以/(需要付出努力)干净地定义一个文件的布局,以便为所有类型的列表项正确使用它们。 使用相对布局并将一个x1放在另一个x2之上。 并根据类型简单地在getView中使x1或x2可见或不可见。 确保在getView中没有繁重的操作。 其中x1和x2是您的一个项目类型的布局。

尝试这个。 但您肯定可以发布您的代码以获得更多帮助。 但建议首先尝试清理。

更新:转到选项2.使用一个RelativeLayout并在其中添加两个LinearLayout。 一个在另一个之上并在第一个LinearLayout中定义一个项类型,在第二个中定义另一个。 使这些容器(LL)在getView中可见或不可见

希望这个建议有所帮助

Lars Vogel的这个教程非常棒。 我强烈推荐使用它。 在没有看到您的JAva代码的情况下,我可以说您需要为列表条目提供两种不同的布局XML。 一个用于左侧图像,另一个用于右侧图像。 然后,在适配器中,为会话的那一部分充气。

这是正确的方法。 我认为发生在你身上的是你在回收的ViewGroup中添加了内容,这些内容传递给了getView而没有删除旧的内容,所以你的新东西被添加到旧的东西之上。 使用新流程,您需要确保循环视图是正确的“方向”,然后删除旧内容并添加新内容。

以下是我在上面链接的Vogella文章中的部分。

getView()方法中,您将扩展基于XML的布局,然后根据此行的Java对象设置各个视图的内容。 LayoutInflator XML布局文件,您可以使用系统服务LayoutInflator 可以通过活动或context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)方法调用访问此服务。

可以通过顶级视图上的findViewById()方法调用找到布局中的各个元素。

顺便说一句,getView()在滚动期间被多次调用,并且调用的顺序是不可预测的。 因此,不要在getView方法中做任何过于密集的事情,否则减速将非常明显。

这是常见问题,已经在StackOverflow中提出过。 但是,首先检查一下android工程师RomainGuy关于getView()方法调用的内容

这不是问题,绝对不能保证调用getView()的顺序也不保证多少次。

因此,您可以最好地处理正确重用现有视图 (行布局)的问题。

或者只需在适配器类中添加此行代码即可。

@Override
public int getViewTypeCount() {

    if (getCount() != 0)
        return getCount();

    return 1;
}

我有确切的问题,我通过不使用convertView解决了它。

基本上,我做的是:

public View getView(int position, View convertView, ViewGroup parent) {

    View rowView = inflater.inflate(R.layout.your_layout, parent, false);

    //Do what you intend to do, populate the TextView, or set the ImageViews, but do them with respect to rowView, not convertView.

    ImageView imageView = (ImageView) rowView.findViewById(R.id.my_picture);

    imageView.setImageResources(R.drawable.sample_picture);

    return rowView;

}

无论您使用1个布局还是2个列表项,这都很有用,希望这会有所帮助:-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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