刷新列表视图中的复选框状态 [英] Refreshing checkbox state in a listview

查看:19
本文介绍了刷新列表视图中的复选框状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有包含 CheckBox 元素的自定义行布局 (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;
    }

}

在我的 Activity(扩展 ListActivity)中,我执行以下操作:

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

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

...然后

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

滚动时效果很好.但是如果我不使用 mCheckStates 数组,它就会失败!我就是不明白为什么.我有 items 数组作为我的 Activity 类的成员,它包含复选框的所有状态!我在 onCheckedChanged() 方法中更新它,就像我更新 mCheckState 一样.所以下面的代码必须工作:

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.

这篇关于刷新列表视图中的复选框状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆