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);
};
我搜索了很多,我开始认为这是不可能的,但我有一个自定义的 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);
};