我有一个自定义适配器的列表视图,其中包含切换按钮,微调器和其他一些视图。
此列表视图显示的项目数量通常超过1个屏幕,这会导致一个我不明白的奇怪问题。
例如: 当我按下列表中第一项的切换按钮时,背景会改变颜色。如果我然后向下滚动到第二个屏幕" (第10-18项)我注意到第11项也被“切换”#34;因为背景也发生了变化。如果我再向下滚动到第20项也被选中了。
我的适配器看起来像这样:
public class ArticlesListAdapter extends ArrayAdapter<Line> {
private List<Line> lineList;
private Context context;
public ArticlesListAdapter(Context context, int textViewResourceId,
List<Line> objects) {
super(context, textViewResourceId, objects);
this.lineList = objects;
this.context = context;
}
public int getCount() {
return lineList.size();
}
public Line getItem(int position) {
return lineList.get(position);
}
public long getItemId(int position) {
return position;
}
public List<Line> GetAllLines() {
return lineList;
}
@SuppressLint("InflateParams")
public View getView(int position, View convertView, ViewGroup parent) {
Viewholder viewholder;
if (convertView == null) {
viewholder = new Viewholder();
convertView = LayoutInflater.from(context).inflate(
R.layout.articles_list_row, null);
viewholder.articleName = (TextView) convertView
.findViewById(R.id.textArticleName);
viewholder.articleAmount = (EditText) convertView
.findViewById(R.id.textArticleAmount);
viewholder.articleButton = (ToggleButton) convertView
.findViewById(R.id.toggleArticleReturn);
viewholder.articleStock = (Spinner) convertView
.findViewById(R.id.spinStockWarehouse);
convertView.setTag(viewholder);
} else {
viewholder = (Viewholder) convertView.getTag();
}
viewholder.articleButton.setTag(position);
if (lineList.get(position).getLineCode().length() > 0) {
viewholder.articleButton.setOnClickListener(RetourArticleListener);
viewholder.articleButton.setOnLongClickListener(RetourCertainAmountArticleListener);
} else {
viewholder.articleButton.setText("Delete");
viewholder.articleButton.setOnClickListener(DeleteArticleListener);
}
String articleNameString = lineList.get(position)
.getLineArticleDescription();
if (articleNameString.length() > 30) {
articleNameString.substring(0, 30);
}
viewholder.articleName.setText(articleNameString);
viewholder.articleName.setTextSize(12);
viewholder.articleAmount.setTag(position);
viewholder.articleAmount.setTextSize(12);
viewholder.articleAmount.setText(lineList.get(position)
.getLineArticleAmount().toString());
if (lineList.get(position).isLineArticleIsOriginal()) {
viewholder.articleStock.setEnabled(false);
}
viewholder.articleStock.setSelection(Integer.parseInt(lineList
.get(position).getLineArticleStock().toString()) - 1);
viewholder.articleStock.setTag(position);
viewholder.articleStock
.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView,
View view, int position, long id) {
final int listPosition = (Integer) adapterView.getTag();
lineList.get(listPosition).setLineArticleStock(
String.valueOf(position + 1));
}
@Override
public void onNothingSelected(AdapterView<?> adapter) {
}
});
// we need to update adapter once we finish with editing
viewholder.articleAmount
.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
final int position = (Integer) v.getTag();
final EditText articleAmount = (EditText) v;
lineList.get(position).setLineArticleAmount(
Double.parseDouble(articleAmount.getText()
.toString().replace(",", ".")));
}
}
});
return convertView;
}
private OnClickListener RetourArticleListener = new OnClickListener() {
@Override
public void onClick(View v) {
boolean on = ((ToggleButton) v).isChecked();
int position = (Integer) v.getTag();
RelativeLayout rl = (RelativeLayout) v.getParent();
if (on) {
// Article returned
rl.setBackgroundColor(Color.RED);
lineList.get(position).setLineArticleReturned(true);
} else {
// Article used
rl.setBackgroundColor(Color.WHITE);
lineList.get(position).setLineArticleReturned(false);
}
}
};
}
答案 0 :(得分:2)
Alex.F指出的问题是ListView的回收行为。解决方案非常简单:
您的订单项已经有一个与我们将使用的颜色状态相对应的布尔值。
在RetourArticleListener中,将if-else语句更改为:
if (on) {
// Article returned
lineList.get(position).setLineArticleReturned(true);
notifyDatasetChanged();
} else {
// Article used
lineList.get(position).setLineArticleReturned(false);
notifyDatasetChanged();
}
notifyDatasetChanged方法将确保调用你的getView()方法。
在你的getView()方法中,检查&#34; LineArticleReturned&#34;的值。并相应地更改背景颜色。在getView方法的末尾添加这个,这样你就可以确保所有必需的变量都被初始化了。我假设你有一个名为getLineArticleReturned()的方法,它在Line类中返回LineArticleReturned的布尔值。
if(lineList.get(position).getLineArticleReturned()==true){
RelativeLayout rl = (RelativeLayout)
convertView.findViewById(R.id.name_of_your_relative_layout_here);
rl.setBackgroundColor(Color.RED);
}else{
rl.setBackgroundColor(Color.WHITE);
}
答案 1 :(得分:1)
这是listView的回收机制问题的明显案例。你应该在this SO Q&A
中阅读它