ListView Items' background get mixed up when scrolling listView

I'm trying to change the background of a specific item in the list view titled "Different Item". As I scroll down the list, all the items' backgrounds are correct. When I reach the end of the list (where "Different Item" is), and scroll back up, there are some random items that get the same background as "Different Item". I believe this is due to the view holder pattern that I'm using and the fact that android recycles each view to use again, but I don't quite understand the issue here, and how to solve it. Here is my MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ListView listView = (ListView)findViewById(R.id.list_view);
        listView.setAdapter(new CustomAdapter(this));
    }
}

Here is my CustomAdapter.java class

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class CustomAdapter extends BaseAdapter {

    private Context mContext;
    private List<String> mItems;

    public CustomAdapter(Context context) {
        mContext = context;
        mItems = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            mItems.add("Item " + i);
        }
        mItems.add("Different Item");
    }

    @Override
    public int getCount() {
        return mItems.size();
    }

    @Override
    public Object getItem(int i) {
        return mItems.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {
        View view;
        ViewHolder viewHolder;
        TextView textView;

        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
                    Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(R.layout.list_item_template, viewGroup, false);
        } else {
            view = convertView;
        }

        if (view.getTag() == null) {
            textView = (TextView)view.findViewById(R.id.items_text_view);
            viewHolder = new ViewHolder(textView);
            view.setTag(viewHolder);
        }
        else {
            viewHolder = (ViewHolder)view.getTag();
            textView = viewHolder.getTextView();
        }

        textView.setText(mItems.get(position));

        if (mItems.get(position).equals("Different Item")) {
            textView.setBackgroundColor(Color.parseColor("#DDDDDD"));
        }

        return view;
    }

    private class ViewHolder {
        private TextView mTextView;

        public ViewHolder(TextView textView) {
            this.mTextView = textView;
        }

        public TextView getTextView() {
            return this.mTextView;
        }
    }
}

Here is my activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></ListView>
</RelativeLayout>

and my list_item_template.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <TextView
        android:id="@+id/items_text_view"
        android:textSize="20sp"
        android:padding="20dp"
        tools:text="test text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

and screenshots of the problem: At first, when I scroll down the list, everything looks fine:

起初,它看起来不错

After scrolling the list view up and down, views get mixed up:

滚动后它会混淆起来


after this section :

 if (mItems.get(position).equals("Different Item")) {
            textView.setBackgroundColor(Color.parseColor("#DDDDDD"));
        }

you should have an else like this:

else
     textView.setBackgroundColor(Color.parseColor("#FFFFFF"));

it will solve your problem.


Your intuition is correct.

When you're setting the background on the "Different Item" view, at some point that view gets recycled and reused by ListView when it goes off screen, and is needed again by the adapter.

It gets reused for other items that aren't "Different Item", and if you don't explicitly reset the background to the default color for those "Item [x]" items, you will run into this problem with inconsistent backgrounds.

Also, an else statement in this context has zero impact on performance.

链接地址: http://www.djcxy.com/p/30562.html

上一篇: ListView和onItemClick创建透明片段

下一篇: 滚动listView时,ListView Items的背景会混淆