在列表视图刷新复选框的状态视图、复选框、状态、列表

2023-09-05 00:11:50 作者:姐是你惹不起的神

我的列表视图定制行布局(list_row.xml),它包含复选框的元素:

I have list view with custom row layout (list_row.xml) that contains CheckBox element:

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:orientation="horizontal"
    android:weightSum="1.0">
    <TableRow>
        <TextView android:id="@+id/name"
            android:layout_weight=".85"
            android:layout_width="0dip"
            android:layout_height="wrap_content"
            android:text="sample"
            android:textSize="24sp">
        </TextView>
        <CheckBox android:id="@+id/enabled"
            android:layout_weight=".15"
            android:layout_width="0dip"
            android:layout_height="wrap_content" 
            android:focusable="false">
        </CheckBox>
    </TableRow>
</TableLayout>

在我的名单上的活动我有ListRowAdapter:

In my list activity I've got ListRowAdapter:

private static class ListRowAdapter extends ArrayAdapter<ListRow> implements
        CompoundButton.OnCheckedChangeListener {

    private List<ListRow> items;
    private LayoutInflater vi;
    private SparseBooleanArray mCheckStates;

    public ListRowAdapter(Context context, int textViewResourceId,
            List<ListRow> objects) {
        super(context, textViewResourceId, objects);
        this.items = objects;
        this.vi = LayoutInflater.from(context);
        this.mCheckStates = new SparseBooleanArray(objects.size());
        for(int i=0;i<mCheckStates.size();i++){
            mCheckStates.put(i,items.get(i).isEnabled());
        }
        Log.i("VIEW", "constructor");
    }

    public boolean isChecked(int position) {
        return mCheckStates.get(position, false);
    }

    public void setChecked(int position, boolean isChecked) {
        mCheckStates.put(position, isChecked);
        items.get(position).setEnabled(isChecked);
        notifyDataSetChanged();
    }

    public void toggle(int position) {
        setChecked(position, !isChecked(position));
    }

    public void onCheckedChanged(CompoundButton buttonView,
            boolean isChecked) {
        ListRow r = (ListRow) buttonView.getTag();
        r.setEnabled(isChecked);
        mCheckStates.put(items.indexOf(r), isChecked);
        Toast.makeText(getContext(), "row " + r.getName() + " changed to "+isChecked, Toast.LENGTH_SHORT).show();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            Log.i("VIEW", "init holder");
            convertView = vi.inflate(R.layout.list_row, null);
            holder = new ViewHolder();
            holder.name = (TextView) convertView.findViewById(R.id.name);
            holder.enabled = (CheckBox) convertView
                    .findViewById(R.id.enabled);
            convertView.setTag(holder);
        } else {
            Log.i("VIEW", "using holder");
            holder = (ViewHolder) convertView.getTag();
        }
        ListRow row = items.get(position);
        if (row != null) {
            holder.name.setText(row.getName());
            holder.enabled.setTag(row);
            holder.enabled.setChecked(mCheckStates.get(position, false));           holder.enabled.setOnCheckedChangeListener(this);
        }
        return convertView;
    }

    static class ViewHolder {
        TextView name;
        CheckBox enabled;
    }

}

在我的活动(扩展ListActivity)我做到以下几点:

In my Activity (that extends ListActivity) I do the following:

private static List<ListRow> rows;
private ListRowAdapter lra;

...然后

... and then

getListView().setItemsCanFocus(false);
getListView().setTextFilterEnabled(true);
rows = initRows();
lra = new ListRowAdapter(this, R.layout.list_row, rows);
setListAdapter(lra);

和工作正常时滚动。但是,如果我不使用 mCheckStates 阵失败!我只是不明白为什么。我有一个项目数组作为我的活动类的成员,它包含复选框的所有状态!我在 onCheckedChanged更新()办法像我更新 mCheckState 。所以下面code的工作:

and that works fine while scrolling. But if I don't use mCheckStates array it fails! I just can't understand why. I have items array as a member of my Activity class and it contains all the states of checkboxes! I update it in onCheckedChanged() method like I update mCheckState. So the following code has to work:

public boolean isChecked(int position) {
    return items.get(position).isEnebled();
}

public void setChecked(int position, boolean isChecked) {
    items.get(position).setEnabled(isChecked);
    notifyDataSetChanged();
}

public void toggle(int position) {
    setChecked(position, !isChecked(position));
}

public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
    ListRow r = (ListRow) buttonView.getTag();
    r.setEnabled(isChecked);
    Toast.makeText(getContext(), "row " + r.getName() + " changed to "+isChecked, Toast.LENGTH_SHORT).show();
}

getView()方法:

holder.enabled.setTag(row);holder.enabled.setChecked(row.isEnabled());

但事实并非如此。它失去复选框状态,而滚动,我不知道为什么。

But it doesn't. It loses checkbox states while scrolling and I don't know why.

推荐答案

我不知道我跟你说有一切,但请记住,的ListView 回收意见为您滚动。这意味着,你不能假定一个视图将在所有默认状态下 getView 的开始。这可能是为什么它没有当你停止每次你得到一个新的视图时重置复选框以正确的工作状态。

I'm not sure I followed everything you said there, but keep in mind that ListView recycles views as you scroll. This means that you cannot assume that a view will be in any default state at the start of getView. This is probably why it doesn't work when you stop resetting the checkbox to the correct state every time you get a new view.

这是说,你有没有考虑使用的ListView 的建成在复选框的工具?将其选择模式, CHOICE_MODE_MULTIPLE ,并用他们的提供的布局之一,如 android.R.layout.simple_list_item_multiple_choice

That said, did you consider using ListViews built in checkbox tool? Set its choice mode to CHOICE_MODE_MULTIPLE and use one of their provided layouts, like android.R.layout.simple_list_item_multiple_choice.