【问题标题】:Getting Checkboxes in a custom ListView to work properly让自定义 ListView 中的复选框正常工作
【发布时间】:2011-09-05 14:11:27
【问题描述】:

我所拥有的是我的列表视图的自定义行布局:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">

<CheckBox
android:id="@+id/chkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

<TextView
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

我在活动中为我的适配器使用此布局:

adapter = new AdapterCustomBoxes(context, R.layout.custom_check_row, (ArrayList<Map<String, String>>) list_values);
list.setAdapter(adapter);    
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

还有一个适配器,这是我的适配器的 getView 方法:

public class AdapterCustomBoxes extends ArrayAdapter<Map<String, String>> {

private List<Map<String, String>> list;
private List<Map<String, String>> orig_list;

private Context upper_context;
private View view;

public AdapterCustomBoxes(Context context, int textViewResourceId, ArrayList<Map<String, String>> items) {
    super(context, textViewResourceId, items);

    this.list = items;
    this.orig_list = items;
    this.upper_context = context;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

view = convertView;

if (view == null) {
    LayoutInflater vi = (LayoutInflater)upper_context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    view = vi.inflate(R.layout.custom_check_row, null);
}

Map<String, String> selectedgroup = new HashMap<String, String>();
selectedgroup = (Map<String, String>) list.get(position);
String itemtext = (String) selectedgroup.get("item_text");

TextView row_text = (TextView) view.findViewById(R.id.text);

row_text.setText(itemtext);

return view;
}
}

现在到了让我感到困惑的地方。当我选中其中一个复选框时,单击的复选框会被选中。但是在没有任何逻辑的情况下,其他行的某些复选框也会被选中。如果我然后滚动列表,每个框的选中状态可能会从我遇到这一行到下一次发生变化。

那么这里有什么问题呢?

我已经尝试在适配器中的视图中添加一个 onclicklistener,然后在触发此侦听器时将显式复选框设置为 cheched/unchecked 但这也无法按预期工作,我单击了一个框,然后另一个被检查了。

所以我猜这是回收视图的问题?我是否必须单独存储检查的状态并每次在 getView 方法中恢复它,这可能是一个解决方案吗?或者有没有更简单的方法?请帮忙;)

那么有人可以给我一个提示吗?非常感谢!

--- 编辑 ---

所以我现在尝试保存复选框的状态是创建一个地图:

private Map<View, Boolean> itm = new HashMap<View, Boolean>();

并在getView方法中保存点击框时的状态:

CheckBox chkbox = (CheckBox) view.findViewById(R.id.chkbox);

    chkbox.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener(){
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            itm.put(buttonView, isChecked);
        }               
    });

    if(itm.containsKey(chkbox)){
        iteminfo_row_chkbox.setChecked( itm.get(chkbox) );
    }else{
        iteminfo_row_chkbox.setChecked(false);
    }

很抱歉,如果这在任何方面都是完全错误的方法,但这不应该有效吗?结果是一样的,整个列表和检查状态都不正确,我做错了什么?

【问题讨论】:

    标签: android listview checkbox adapter


    【解决方案1】:

    一些题外话:

    首先你不需要这个:

    Map<String, String> selectedgroup = new HashMap<String, String>();
    

    你可以这样做:

    Map<String, String> selectedgroup = (Map<String, String>) list.get(position);
    

    另外,您确定需要 TextView 吗?复选框也可以包含文本。

    关于您的问题,您如何保存选中的复选框?您应该在返回视图时设置复选框,特别是在重用视图时。

    -- 编辑--

    你为什么不创建一个这样的私有类?

    private class ListItem{
        String text;
        boolean value;
    }
    

    然后你可以只使用List&lt;ListItem&gt;,而不是List&lt;Map&lt;String,String&gt;&gt;

    关于onCheckedChangeListener,您可以使用复选框中的文本迭代列表以找到正确的位置,然后更改值。如果文本不是唯一的, 而不是使用onCheckedChangeListener,您可以在ListView 上使用OnItemClickListener,它保存点击的位置。

    【讨论】:

    • 感谢题外话!目前我没有保存选择状态,这似乎是问题所在?那么我怎样才能设法保存状态以及如何将此信息返回给活动?非常感谢。
    【解决方案2】:

    好的,我想我明白了,我使用 selectedgroup 映射中的静态 id 值作为 itm 映射中的键来查找复选框的选中/未选中状态。使用视图是错误的方法,因为它们不能用作键。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-27
      • 1970-01-01
      相关资源
      最近更新 更多