代码之家  ›  专栏  ›  技术社区  ›  Hetiwos

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

  •  0
  • Hetiwos  · 技术社区  · 9 年前

    我有一个带有切换按钮、微调器和其他一些视图的定制适配器的列表视图。

    这个列表视图显示的项目比正常情况下在一个屏幕上可以容纳的项目多,这导致了一个奇怪的问题,我不明白。

    例如: 当我按下列表中第一个项目的切换按钮时,背景会改变颜色。如果我向下滚动到“第二个屏幕”(项目10-18),我注意到第11个项目也已“切换”,因为背景也已更改。如果我再向下滚动到第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 回复  |  直到 9 年前
        1
  •  2
  •   Frank D.    9 年前

    正如Alex.F所指出的,问题是ListView的回收行为。解决方案非常简单:

    您的Line项目已经有一个布尔值,它对应于我们将使用的颜色状态。

    在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()方法中,检查“LineArticleReturned”的值并相应地更改背景颜色。将其添加到getView方法末尾的某个位置,以便确保所有必需的变量都已初始化。我假设您有一个名为getLineArticleReturned()的方法,该方法返回Line类中LineArticle Returned的布尔值。

     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);
     }
    
        2
  •  1
  •   Community miroxlav    7 年前

    这显然是listView的回收机制存在问题的一个例子。例如,你应该在 this SO Q&A