从自定义适配器android中删除项目

时间:2016-09-28 19:41:48

标签: android listview custom-adapter notifydatasetchanged

我无法在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();并且问题仍然存在。我可以使其工作的唯一(和可怕的)解决方案是在删除后重新创建活动(recreate();)。屏幕闪烁,可怕,但它功能齐全。现在我有空闲时间,我要求你们帮忙。

以下是使用适配器的活动的代码:

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中删除)。

任何sugestions?

1 个答案:

答案 0 :(得分:0)

您的问题可能就在这里

@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();
    }

您正在删除正确的项目,但是这会阻止在notifydatasetchanged之后更新视图,也许会尝试这样的事情

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)));