Android Java 将 ListView 更改为 select 多行(用于删除)而无需单独的 class

Android Java change ListView to select multiple lines (for deleting) without a separate class

我搜索了很多,我开始认为这是不可能的,但我有一个自定义的 ListView,它处于膨胀布局中并放在弹出窗口中 window。这些线是使用适配器从布局文件制作的。列表中的每一项都是可点击的,并将用户带到不同的列表。我还想这样做,这样当我长按一个项目时,它 select 就是那个项目 然后允许我 select 多行,然后我有一个单独的按钮来删除它们。需要明确的是,我不希望每行都有一个复选框(没有空间)。只是要突出显示的行。我被困在“select 那个项目”部分,更不用说“select 多行”了。我将把我的代码截断到相关部分。注意:masterRecord是ListView的名称。

private void fillList() {

        int numRows = mainDB.numRowsMaster();

        if (numRows == 0) {
            Toast.makeText(getApplicationContext(), "Nothing to load!", Toast.LENGTH_SHORT).show();
            return;
        }

        cursor = mainDB.getAllRowsMaster();

        startManagingCursor(cursor);

        String[] fromFieldNames = new String[]{DBAdapter.KEY_MASNAMECOL, DBAdapter.KEY_MASLASTDATECOL, DBAdapter.KEY_MASTOTALTIMEASCLOCKCOL};
        int[] toViewIds = new int[]{R.id.rowName, R.id.rowLastDate, R.id.rowTotalTime};

        SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(this, R.layout.master_list_row, cursor, fromFieldNames, toViewIds);

        masterRecord.setAdapter(cursorAdapter);
        masterRecord.setLongClickable(true);

    }
private void listItemClick() {
        masterRecord.setOnItemClickListener((parent, viewClicked, position, idInDB) -> {

//Bunch of code here to make the next listview popup and make a cursor adapter. This all works fine.

        });

        masterRecord.setOnItemLongClickListener((parent, view, position, idInDB) -> {

            Toast.makeText(getApplicationContext(), "Is this working?", Toast.LENGTH_SHORT).show();

            masterRecord.setClickable(false); //This doesn't make a difference even though it's running.
//The items in masterRecord are still clickable. Separate issue that I'm not worried about ATM.
            masterRecord.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
            masterRecord.setMultiChoiceModeListener(new ListView.MultiChoiceModeListener() {
                @Override
                public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
                    Toast.makeText(getApplicationContext(), "Here4", Toast.LENGTH_SHORT).show();
                }

                @Override
                public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                    Toast.makeText(getApplicationContext(), "Here1", Toast.LENGTH_SHORT).show();
                    return false;
                }

                @Override
                public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                    Toast.makeText(getApplicationContext(), "Here3", Toast.LENGTH_SHORT).show();
                    return false;
                }

                @Override
                public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                    Toast.makeText(getApplicationContext(), "Here2", Toast.LENGTH_SHORT).show();
                    return false;
                }

                @Override
                public void onDestroyActionMode(ActionMode mode) {
                    Toast.makeText(getApplicationContext(), "Here5", Toast.LENGTH_SHORT).show();
                }
            });

            return true;
        });
    }

祝酒词只是为了让我可以看到屏幕上有什么 运行 或没有。 “这管用吗?”是我长按时唯一出现的东西。什么都没有 selected,如果我一直按住,它只会继续做同样的事情。如果我然后短按,它只会执行正常的短按操作。

我找到了 Checkable 小部件并且非常兴奋,但似乎也无法使它工作。我看到的教程和其他信息对 ListView 有一个单独的 class,但这似乎有点过分了。这真的是唯一的方法吗?如果我遗漏了任何相关代码,请告诉我,我会进行编辑以包括在内。谢谢。

我在另一个 post(有点)中找到了答案,所以我要 post 我在这里所做的,link 他们的答案也是如此。

按照此答案进行设置: 这包括制作可在行布局上使用的可绘制对象。请记住,您可以将可绘制背景应用于行布局的任何部分(包括整个布局)。当它被选中时,它会改变你应用它的任何东西。

所有这些都假定您已经设置了带有适配器的 ListView。

注意:masterRecord 是我的 ListView 的名称。

这是我的项目长按监听器:

masterRecord.setOnItemLongClickListener((parent, view, position, idInDB) -> {

//On first long click, it sets the choice mode to multiple.
            masterRecord.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

//selections is an Integer ArrayList. First entry just sets whatever was long clicked to 
//checked, and adds the position into the array.
//I'm recycling layouts (rather than making a bunch), so this also sets an already 
//existing button to do something.
            if (selections.size() == 0) {
                masterRecord.setItemChecked(position, true);
                selections.add(position);
                switchLists.setText("clear selection");
                switchLists.setOnClickListener(clearSelection);
            } 
//In the event someone long clicks on another item, if it's not already selected, it 
//will get selected. Otherwise it will get unselected.
//This also shows up in the regular item click listener.
            else
            if (!selections.contains(position)) {
                masterRecord.setItemChecked(position, true);
                selections.add(position);
            } else if (selections.contains(position)) {
                masterRecord.setItemChecked(position, false);
                selections.remove(Integer.valueOf(position));
//The next if will set everything back to normal if everything is manually deselected
                if (selections.size() == 0) {
                    switchLists.setText("View by date");
                    switchLists.setOnClickListener(showDateList);
                    masterRecord.setChoiceMode(ListView.CHOICE_MODE_NONE);
                }
            }
            return true;
        });

接下来是常规的 onItemClick()

masterRecord.setOnItemClickListener((AdapterView<?> parent, View viewClicked, int position, long idInDB) -> {

//This is basically the same code as in the long click listener.
            if (selections.size() > 0) {

                if (!selections.contains(position)) {
                    masterRecord.setItemChecked(position, true);
                    selections.add(position);
                } else if (selections.contains(position)) {
                    masterRecord.setItemChecked(position, false);
                    selections.remove(Integer.valueOf(position));
                    if (selections.size() == 0) {
                        switchLists.setText("View by date");
                        switchLists.setOnClickListener(showDateList);
                        masterRecord.setChoiceMode(ListView.CHOICE_MODE_NONE);
                    }
                }
//return is used here to stop the rest of the onItemClick from running, since it should
//only run when I'm not trying to multi-select.
                return;
            }

奖励 - 清除选择按钮:

View.OnClickListener clearSelection = v -> {
//A loop which will run through the selections ArrayList and uncheck all the items
//in the listview, and remove them from the ArrayList.
        for (int i = selections.size()-1; i >= 0; i--) {
            masterRecord.setItemChecked(selections.get(i), false);
            selections.remove(i);
        }
//Then it just sets everything back to original.
        switchLists.setText("View by date");
        switchLists.setOnClickListener(showDateList);
    };