Android ListView项目在滑动时获取另一个项目的背景色

Android ListView项目在滑动时获取另一个项目的背景色,android,android-listview,Android,Android Listview,我创建了一个带有自定义适配器的ListView,该适配器扩展了SimpleAdapter。第五项是粉红色的。当我上下滑动时,其他项目会随机获得与第五个项目相同的背景颜色。我觉得很奇怪,为什么 屏幕截图: :启动后直接启动应用程序 :在我上下滑动几次后,应用程序 文件: MainActivity.java: package com.example.test; import java.util.ArrayList; import java.util.List; import android.ap

我创建了一个带有自定义适配器的ListView,该适配器扩展了SimpleAdapter。第五项是粉红色的。当我上下滑动时,其他项目会随机获得与第五个项目相同的背景颜色。
我觉得很奇怪,为什么

屏幕截图:
:启动后直接启动应用程序
:在我上下滑动几次后,应用程序

文件:
MainActivity.java:

package com.example.test;

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

import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ListAdapter;

public class MainActivity extends ListActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        List<Car> cars = getData();
        ListAdapter adapter = new CarListAdapter(this, cars, android.R.layout.simple_list_item_2, new String[] {
                Car.KEY_MODEL, Car.KEY_MAKE }, new int[] { android.R.id.text1, android.R.id.text2 });
        this.setListAdapter(adapter);
    }

    private List<Car> getData() {
        List<Car> cars = new ArrayList<Car>();
        for(int i = 0; i < 15; i++) {
            cars.add(new Car("Car "+i, i+""));
        }
        return cars;
    }
}
package com.example.test;
导入java.util.ArrayList;
导入java.util.List;
导入android.app.ListActivity;
导入android.os.Bundle;
导入android.widget.ListAdapter;
公共类MainActivity扩展了ListActivity{
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List cars=getData();
ListAdapter=new CarListAdapter(这个,cars,android.R.layout.simple\u list\u item\u 2,新字符串[]){
Car.KEY_MODEL,Car.KEY_MAKE},新int[]{android.R.id.text1,android.R.id.text2});
这个.setListAdapter(适配器);
}
私有列表getData(){
List cars=new ArrayList();
对于(int i=0;i<15;i++){
添加(新车(“车”+i,i+);
}
返回车辆;
}
}


CarListAdapter.java:

package com.example.test;

import java.util.List;
import java.util.Map;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SimpleAdapter;

public class CarListAdapter extends SimpleAdapter {
    private List<Car> cars;
    private int[] colors = new int[] { 0x30ff2020, 0x30ff2020, 0x30ff2020 };

    @SuppressWarnings("unchecked")
    public CarListAdapter(Context context,
            List<? extends Map<String, String>> cars, int resource,
            String[] from, int[] to) {
        super(context, cars, resource, from, to);
        this.cars = (List<Car>) cars;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = super.getView(position, convertView, parent);

        if (position == 5) {
            int colorPos = position % colors.length;
            view.setBackgroundColor(colors[colorPos]);
        }

        return view;
    }

}
package com.example.test;
导入java.util.List;
导入java.util.Map;
导入android.content.Context;
导入android.view.view;
导入android.view.ViewGroup;
导入android.widget.simpledapter;
公共类CarListAdapter扩展了SimpleAdapter{
私家车名单;
私有int[]颜色=新int[]{0x30ff2020,0x30ff2020,0x30ff2020};
@抑制警告(“未选中”)
公共CarListAdapter(上下文,
列表

这是因为您编写的适配器不正确,并且在视图回收机制的帮助下基本上产生了一些错误,您可以在该机制上阅读更多信息。删除此行:

 View view = super.getView(position, convertView, parent);
并写下以下内容:

View row;
LayoutInflater inflator = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflator.inflate(R.layout.new_row, null);
if (position == 5) {
        int colorPos = position % colors.length;
        row .setBackgroundColor(colors[colorPos]);
}

return row ;
更新:

使用
getView
方法时,需要在layouts文件夹中为行创建布局,并将其用作每行的布局。在运行
getView
期间(为在
ListView
中创建的每一行运行的方法)您可以根据特定行在列表中的
位置
或附加到特定位置列表项的其他数据,对特定行进行所需的更改。您可以这样做(最好创建一个
视图支架
,该支架将从
视图
的角度描述行的视觉外观),如下所示:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row;
    final ViewHolder holder = new ViewHolder();
    LayoutInflater inflator = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    row = inflator.inflate(R.layout.new_row, null);
    holder.tvId = (TextView) row.findViewById(R.id.text_id);
    holder.tvId.setText(position);
    ...

    if (position == 5) {
        int colorPos = position % colors.length;
        row .setBackgroundColor(colors[colorPos]);
    }
    return row ;
}

static class ViewHolder
{
  TextView tvId;
  TextView tvTitle;
}
更新2: 我想正如评论中所说,这是一个更好的选择:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    if (convertView == null) {
        holder = new ViewHolder();
        LayoutInflater inflator = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflator.inflate(R.layout.list, null);
        holder.tvId = (TextView) convertView.findViewById(R.id.text_id);
        ...
        if (position == 5) {
           int colorPos = position % colors.length;
           convertView.setBackgroundColor(colors[colorPos]);
        }
        convertView.setTag(holder);
    }
    else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.tvId.setText(position);
    ...

    return convertView;
}

static class ViewHolder
{
  TextView tvId;
  TextView tvTitle;
}

但我发现这有问题,而且并不总是正常工作。

在getView中,您没有处理其他情况(当它不等于5时):

原因是它使用旧视图进行重用


另外,您应该使用android:cacheColorHint=“#00000000”。这里有一篇关于它的文章:

错误:LayoutFlater充气器=(LayoutFlater)getSystemService(Context.LAYOUT_充气器_SERVICE)处的类型CarListAdapter的方法getSystemService(String)未定义;getSystemService是具有上下文的对象的方法,例如活动。因此,您需要将活动传递给适配器,或使用正在传递的上下文对象。例如context.getSystemServiceYeah可以工作,但现在文本不可见/不在此处:这样做会失去视图循环的所有好处。您应该只增加一个新的r如果
convertView
为空,则为ow。诀窍是设置所有可能已更改的属性。例如,如果
position!=5
@EmilAdz No,则需要设置默认背景色。您的答案只会带来我们在Auroratic的注释中看到的问题。此代码用于使用
BaseAdapter
时,但在我们看到的案例是扩展的,它在重用视图和设置子视图上的所有值方面已经做得很好了。正确的答案是nicopico说的:使用
else
子句处理
位置!=5
的案例。是的,请参阅另一个
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row;
    final ViewHolder holder = new ViewHolder();
    LayoutInflater inflator = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    row = inflator.inflate(R.layout.new_row, null);
    holder.tvId = (TextView) row.findViewById(R.id.text_id);
    holder.tvId.setText(position);
    ...

    if (position == 5) {
        int colorPos = position % colors.length;
        row .setBackgroundColor(colors[colorPos]);
    }
    return row ;
}

static class ViewHolder
{
  TextView tvId;
  TextView tvTitle;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    if (convertView == null) {
        holder = new ViewHolder();
        LayoutInflater inflator = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflator.inflate(R.layout.list, null);
        holder.tvId = (TextView) convertView.findViewById(R.id.text_id);
        ...
        if (position == 5) {
           int colorPos = position % colors.length;
           convertView.setBackgroundColor(colors[colorPos]);
        }
        convertView.setTag(holder);
    }
    else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.tvId.setText(position);
    ...

    return convertView;
}

static class ViewHolder
{
  TextView tvId;
  TextView tvTitle;
}
  if (position == 5) {
            int colorPos = position % colors.length;
            view.setBackgroundColor(colors[colorPos]);
        }
  else view.setBackgroundColor(defaultColor);