从自定义适配器中删除项目 android
Delete items from custom adapter android
我在 android 中的 ListView 上进行多重删除时遇到问题。
1) 我已经创建了一个 CustomAdapter 以使用一些按钮和文本自定义每一行(我将只把我认为最重要的放在这里):
public class PlayableCustomAdapter extends ArrayAdapter<String> {
private final boolean[] checkedItems;
private final LayoutInflater mInflater;
private final ActivityCallback activityCallback;
public PlayableCustomAdapter(Context context, ActivityCallback activityCallback,
List<String> files) {
super(context, NO_SELECTION);
this.activityCallback = activityCallback;
this.mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.checkedItems = new boolean[files.size()];
addAll(files);
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
Holder holder;
if (row == null) {
row = mInflater.inflate(R.layout.list_view_row_song, null);
holder = new Holder();
holder.text = (TextView) row.findViewById(R.id.tvFileName);
holder.configs = (TextView) row.findViewById(R.id.tvFileConfiguration);
holder.checkBox = (CheckBox) row.findViewById(R.id.cbDelete);
holder.playButton = (ImageButton) row.findViewById(R.id.btnPlay);
holder.settingsButton = (ImageButton) row.findViewById(R.id.btnSettings);
holder.text.setText(getItem(position));
holder.configs.setText(getLyricConfiguration(getItem(position)));
row.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.playButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startPrompter(position);
}
});
holder.settingsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startSettings(position);
}
});
holder.text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startEditFile(position);
}
});
holder.checkBox.setChecked(checkedItems[position]);
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
checkedItems[position] = true;
activityCallback.showContent();
} else {
verifySelectedItems(position);
}
}
});
return row;
}
private void verifySelectedItems(int position) {
checkedItems[position] = false;
for (boolean checked : checkedItems) {
if (checked)
return;
}
activityCallback.hideContent();
}
public boolean isChecked(int position) {
return checkedItems[position];
}
@Override
public void remove(String s) {
verifySelectedItems(getPosition(s));
super.remove(s);
notifyDataSetChanged();
}
static class Holder {
TextView text;
TextView configs;
ImageButton playButton;
CheckBox checkBox;
ImageButton settingsButton;
}
2) 我已经在 Activity 中使用了这个适配器,除了多次删除之外,一切都很好用。只有当我清除所有适配器项目时,列表视图才会正确更新。
当我删除一个或多个项目时,适配器似乎没问题。所有位置都正确通过。但我不知道如何,只有列表末尾的项目从视图中删除。
3) 如您所见,我在删除后使用notifyDataSetChanged();
,但问题仍然存在。我可以让它工作的唯一(也是可怕的)解决方案是在删除后重新创建 Activity (recreate();
)。屏幕闪烁,很糟糕,但功能齐全。现在我有一些空闲时间,我向你们寻求帮助。
这是使用适配器的 activity 中的代码:
private void deleteFilesFromDisk(List<Integer> positionsToDelete, ArrayAdapter adapter) {
File[] files = getAppFiles();
for (int position : positionsToDelete) {
if (files[position].delete()) {
adapter.remove(fileNames.get(position));
} else
showMessage(R.string.delete_file_error, fileNames.get(position));
}
recreate(); // Horrible workaround, but it works!
}
请记住,此方法只是示例。特别是最后一行。如果没有 recreation 命令,只会删除列表末尾的项目(至少在视觉上,从 UI)。
有什么建议吗?
你的问题可能出在这里
@Override
public void remove(String s) {
verifySelectedItems(getPosition(s));
super.remove(s);
notifyDataSetChanged();
}
您从适配器中删除了项目,但未从 checkedItems
中删除索引
如果我是你,我不会使用布尔数组来跟踪选中的项目,而是使用 ArrayList<Integer>
并将所有选中的位置保留在列表中。
然后您可以将该方法更改为如下所示
@Override
public void remove(String s) {
int pos = getPosition(s);
verifySelectedItems(pos);
remove(s);
checkedItems.remove(Integer.valueOf(pos));
notifyDataSetChanged();
}
然后这个...
private void verifySelectedItems(int position) {
checkedItems[position] = false;
for (boolean checked : checkedItems) {
if (checked)
return;
}
activityCallback.hideContent();
}
可以这样
private void verifySelectedItems(int position) {
if(!checkedItems.contains(position)) {
activityCallback.hideContent();
}
}
编辑:
抱歉,我没有正确阅读问题,我认为这是你的问题
if (row == null) {
row = mInflater.inflate(R.layout.list_view_row_song, null);
holder = new Holder();
holder.text = (TextView) row.findViewById(R.id.tvFileName);
holder.configs = (TextView) row.findViewById(R.id.tvFileConfiguration);
holder.checkBox = (CheckBox) row.findViewById(R.id.cbDelete);
holder.playButton = (ImageButton) row.findViewById(R.id.btnPlay);
holder.settingsButton = (ImageButton) row.findViewById(R.id.btnSettings);
holder.text.setText(getItem(position));
holder.configs.setText(getLyricConfiguration(getItem(position)));
row.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
您正在删除正确的项目,但这会阻止在通知数据集更改后更新视图,也许可以尝试这样的操作
if(convertView == null) {
convertView = mInflater.inflate(R.layout.list_view_row_song, null);
}
Holder holder = new Holder();
holder.text = (TextView) convertView.findViewById(R.id.tvFileName);
holder.configs = (TextView) convertView.findViewById(R.id.tvFileConfiguration);
holder.checkBox = (CheckBox) convertView.findViewById(R.id.cbDelete);
holder.playButton = (ImageButton) convertView.findViewById(R.id.btnPlay);
holder.settingsButton = (ImageButton) convertView.findViewById(R.id.btnSettings);
holder.text.setText(getItem(position));
holder.configs.setText(getLyricConfiguration(getItem(position)));
我在 android 中的 ListView 上进行多重删除时遇到问题。
1) 我已经创建了一个 CustomAdapter 以使用一些按钮和文本自定义每一行(我将只把我认为最重要的放在这里):
public class PlayableCustomAdapter extends ArrayAdapter<String> {
private final boolean[] checkedItems;
private final LayoutInflater mInflater;
private final ActivityCallback activityCallback;
public PlayableCustomAdapter(Context context, ActivityCallback activityCallback,
List<String> files) {
super(context, NO_SELECTION);
this.activityCallback = activityCallback;
this.mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.checkedItems = new boolean[files.size()];
addAll(files);
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
Holder holder;
if (row == null) {
row = mInflater.inflate(R.layout.list_view_row_song, null);
holder = new Holder();
holder.text = (TextView) row.findViewById(R.id.tvFileName);
holder.configs = (TextView) row.findViewById(R.id.tvFileConfiguration);
holder.checkBox = (CheckBox) row.findViewById(R.id.cbDelete);
holder.playButton = (ImageButton) row.findViewById(R.id.btnPlay);
holder.settingsButton = (ImageButton) row.findViewById(R.id.btnSettings);
holder.text.setText(getItem(position));
holder.configs.setText(getLyricConfiguration(getItem(position)));
row.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
holder.playButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startPrompter(position);
}
});
holder.settingsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startSettings(position);
}
});
holder.text.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startEditFile(position);
}
});
holder.checkBox.setChecked(checkedItems[position]);
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
checkedItems[position] = true;
activityCallback.showContent();
} else {
verifySelectedItems(position);
}
}
});
return row;
}
private void verifySelectedItems(int position) {
checkedItems[position] = false;
for (boolean checked : checkedItems) {
if (checked)
return;
}
activityCallback.hideContent();
}
public boolean isChecked(int position) {
return checkedItems[position];
}
@Override
public void remove(String s) {
verifySelectedItems(getPosition(s));
super.remove(s);
notifyDataSetChanged();
}
static class Holder {
TextView text;
TextView configs;
ImageButton playButton;
CheckBox checkBox;
ImageButton settingsButton;
}
2) 我已经在 Activity 中使用了这个适配器,除了多次删除之外,一切都很好用。只有当我清除所有适配器项目时,列表视图才会正确更新。 当我删除一个或多个项目时,适配器似乎没问题。所有位置都正确通过。但我不知道如何,只有列表末尾的项目从视图中删除。
3) 如您所见,我在删除后使用notifyDataSetChanged();
,但问题仍然存在。我可以让它工作的唯一(也是可怕的)解决方案是在删除后重新创建 Activity (recreate();
)。屏幕闪烁,很糟糕,但功能齐全。现在我有一些空闲时间,我向你们寻求帮助。
这是使用适配器的 activity 中的代码:
private void deleteFilesFromDisk(List<Integer> positionsToDelete, ArrayAdapter adapter) {
File[] files = getAppFiles();
for (int position : positionsToDelete) {
if (files[position].delete()) {
adapter.remove(fileNames.get(position));
} else
showMessage(R.string.delete_file_error, fileNames.get(position));
}
recreate(); // Horrible workaround, but it works!
}
请记住,此方法只是示例。特别是最后一行。如果没有 recreation 命令,只会删除列表末尾的项目(至少在视觉上,从 UI)。
有什么建议吗?
你的问题可能出在这里
@Override
public void remove(String s) {
verifySelectedItems(getPosition(s));
super.remove(s);
notifyDataSetChanged();
}
您从适配器中删除了项目,但未从 checkedItems
中删除索引
如果我是你,我不会使用布尔数组来跟踪选中的项目,而是使用 ArrayList<Integer>
并将所有选中的位置保留在列表中。
然后您可以将该方法更改为如下所示
@Override
public void remove(String s) {
int pos = getPosition(s);
verifySelectedItems(pos);
remove(s);
checkedItems.remove(Integer.valueOf(pos));
notifyDataSetChanged();
}
然后这个...
private void verifySelectedItems(int position) {
checkedItems[position] = false;
for (boolean checked : checkedItems) {
if (checked)
return;
}
activityCallback.hideContent();
}
可以这样
private void verifySelectedItems(int position) {
if(!checkedItems.contains(position)) {
activityCallback.hideContent();
}
}
编辑:
抱歉,我没有正确阅读问题,我认为这是你的问题
if (row == null) {
row = mInflater.inflate(R.layout.list_view_row_song, null);
holder = new Holder();
holder.text = (TextView) row.findViewById(R.id.tvFileName);
holder.configs = (TextView) row.findViewById(R.id.tvFileConfiguration);
holder.checkBox = (CheckBox) row.findViewById(R.id.cbDelete);
holder.playButton = (ImageButton) row.findViewById(R.id.btnPlay);
holder.settingsButton = (ImageButton) row.findViewById(R.id.btnSettings);
holder.text.setText(getItem(position));
holder.configs.setText(getLyricConfiguration(getItem(position)));
row.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
}
您正在删除正确的项目,但这会阻止在通知数据集更改后更新视图,也许可以尝试这样的操作
if(convertView == null) {
convertView = mInflater.inflate(R.layout.list_view_row_song, null);
}
Holder holder = new Holder();
holder.text = (TextView) convertView.findViewById(R.id.tvFileName);
holder.configs = (TextView) convertView.findViewById(R.id.tvFileConfiguration);
holder.checkBox = (CheckBox) convertView.findViewById(R.id.cbDelete);
holder.playButton = (ImageButton) convertView.findViewById(R.id.btnPlay);
holder.settingsButton = (ImageButton) convertView.findViewById(R.id.btnSettings);
holder.text.setText(getItem(position));
holder.configs.setText(getLyricConfiguration(getItem(position)));