Android自定义适配器Listview 1选择会导致多个选择

时间:2015-02-12 14:44:51

标签: android android-listview baseadapter getview

我有一个自定义适配器的列表视图,其中包含切换按钮,微调器和其他一些视图。

此列表视图显示的项目数量通常超过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);
        }

    }
};
}

2 个答案:

答案 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

中阅读它