【问题标题】:Android: Wrong item checked when filtering listviewAndroid:过滤列表视图时检查了错误的项目
【发布时间】:2011-12-14 01:13:35
【问题描述】:

我遇到了与这个问题相同的问题:Wrong item checked when filtering ListView in android

正如上面问题中所建议的,我有一个包含所有 selectedIds 的 Hashset,但是当光标重新填充选中的项目时,我不知道如何使用它。

我的问题只是表面问题 - 例如:

  • “Facebook”在未过滤列表中位于第 5 位。
  • 用户搜索“人脸”,只有“Facebook”出现在过滤列表的第 1 位。
  • 用户选中“Facebook”并返回未过滤列表。
  • 选中的项目是列表中的第 1 项,而不是“Facebook”(位于第 5 位)。

注意: 除了这个问题,其他一切都很好。 例如,“删除”会删除正确的项目,因为我使用 selectedIds 来执行此操作(即使选中的项目是错误的)。

单击列表项:

OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {

                //gets the Bookmark ID of selected position
                    Cursor cursor = (Cursor)parent.getItemAtPosition(position);
                    String bookmarkID = cursor.getString(0);

                    boolean currentlyChecked = checkedStates.get(position);
                    checkedStates.set(position, !currentlyChecked);

                    if (!selectedIds.contains(bookmarkID)) {

                        selectedIds.add(bookmarkID);
                        selectedLines.add(position);

                    } else {

                        selectedIds.remove(bookmarkID);
                        selectedLines.remove(position);


                        }

            }
        };

光标内部:- 这就是问题所在。

这会重新填充已检查的项目 - 问题是它按位置 (pos) 执行此操作,并且该项目在过滤列表中的正确位置是什么,而不是它在未过滤列表中的位置 - 导致错误标记的项目。

CheckedTextView markedItem = (CheckedTextView) row.findViewById(R.id.btitle);
markedItem.setChecked(checkedStates.get(pos));

不胜感激!

【问题讨论】:

    标签: android android-listview


    【解决方案1】:

    这是我的解决方案:

    • 过滤后要在列表视图中选择一个项目,一开始我得到了错误的项目,因为我使用了这个:

      ItemData item = listItems.get(position);
      

    正确的做法应该是这样的:

        ItemData item = (ItemData) parent.getItemAtPosition(position);
    
    • 要删除过滤后的项目,我试过这个:

      for(int i=0;i<listItems.size();i++){
          if(listItems.get(i).getItemID() == item.getItemID()){
              listItems.remove(i);
              myAdapter.notifyDataSetChanged();
         }
      }
      

    但这不起作用,因为我的自定义适配器。在我的自定义适配器中,要使用过滤器,我有两个 listItems:

        ArrayList<ItemData> listItemsToShow = new ArrayList< ItemData >();
        ArrayList< ItemData > listItemsBackup = new ArrayList< ItemData >();
    

    所以要删除一个项目,我在自定义适配器中添加了新方法:

        public void deleteItem(String itemID) {
        for (int i = 0; i < listItemsToShow.size(); i++) {
            if (listItemsToShow.get(i).getId().equals(itemID)) {
                listItemsToShow.remove(i);
                break;
            }
        }
    
        for (int i = 0; i < listItemsBackup.size(); i++) {
            if (listItemsBackup.get(i).getId().equals(itemID)) {
                listItemsBackup.remove(i);
                break;
            }
        }
    

    最后在列表视图中删除一个项目:

        subjectBaseAdapter.deleteItem(subject.getId());
        subjectBaseAdapter.notifyDataSetChanged();
    

    希望有帮助

    【讨论】:

      【解决方案2】:

      解决了这个问题。 正如我添加到我的问题中所建议的那样,当您填充复选框时,其他列表/哈希集应确定是否将项目标记为选中。

      使用我的代码:

      //first you will need to get the current item ID
      String bookmarkID = cursor.getString(0);
      
      //Then, check if the current ID is in the selectedIds hash/list
      //If true - mark current item view as checked, else - uncheck.
              CheckedTextView markedItem = (CheckedTextView) row.findViewById(R.id.btitle);
              if (selectedIds.contains(new String(bookmarkID))) {
                  markedItem.setChecked(true);
      
              } else {
                  markedItem.setChecked(false);
      }
      

      真的希望这对任何人都有帮助! :)

      【讨论】:

      • 我对实现这个有点困惑。我有一个带有列表视图的 SimpleCursorAdapter。你是如何初始化checkedStates、selectedIds和selectedLines的?另外,答案中提到的列表/哈希集是否会确定标记为已检查的项目,需要自定义适配器还是我可以使用 SimpleCursorAdapter?
      • @movingahead 无法在此处真正发布代码(已解决的问题)......要么开始一个新问题,要么给我发电子邮件(我在 gmail 的昵称),我会尽力提供帮助。
      • 我在这里问了一个新问题stackoverflow.com/questions/9399941/… 如果您能提供帮助,那就太好了。
      • @movingahead 在那里发布了答案。
      【解决方案3】:

      难道只是你的 ListView 不知道数据集发生了变化吗?在你的适配器上调用 notifyDatSetChanged() 让它知道。

      my_adapter.notifyDataSetChanged();
      

      这将使用更新的数据强制重绘列表。

      【讨论】:

      • 它知道。不幸的是,这不是问题。
      猜你喜欢
      • 2011-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-07
      相关资源
      最近更新 更多