簡體   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