使用 CursorAdapter 在列表视图中维护复选框状态 [英] Maintaining checkbox states in listview with CursorAdapter

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

问题描述

对于我的 Android 项目,我有一个列表视图,其中每个项目都有一个复选框.数据是通过使用 CursorAdapter 类从 SQLite 数据库加载的.但是,每当我滚动时,复选框位置都会移动并向下移动到列表视图的下一部分.我该如何解决这个问题?).

解决方案

原因: ListView 重复使用视图.

解决方案:

class VocabCursorAdapter 扩展 CursorAdapter {列表<整数>selectedItemsPositions;//存储所有选中项的位置public VocabCursorAdapter(上下文上下文,Cursor c,int flags){超级(上下文,c,0);selectedItemsPositions = new ArrayList<>();}@覆盖公共视图新视图(上下文上下文,光标光标,视图组视图组){查看视图 = LayoutInflater.from(context).inflate(R.layout.item_vocab, viewGroup, false);CheckBox box = (CheckBox) view.findViewById(R.id.editCheckbox);box.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {@覆盖public void onCheckedChanged(CompoundButton复合按钮,布尔b){int position = (int) CompoundButton.getTag();如果 (b) {//检查它是否已经被选中如果 (!selectedItemsPositions.contains(position))selectedItemsPositions.add(position);} 别的 {//如果未选中的选中项,则删除位置selectedItemsPositions.remove((Object) position);}}});返回视图;}@覆盖public void bindView(视图视图,上下文上下文,光标光标){//你的其他东西CheckBox box = (CheckBox) view.findViewById(R.id.editCheckbox);box.setTag(cursor.getPosition());如果(selectedItemsPositions.contains(cursor.getPosition()))box.setChecked(true);别的box.setChecked(false);}}

For my Android project, I have a listview which has a checkbox for every item. The data is loaded from an SQLite database by using a CursorAdapter class. However, whenever I scroll, the checkbox positions will get moved and get carried down to the next part of the listview. How can I fix this problem? GIF of my CheckBox Problem Here's my Cursor Adapter Class:

public class VocabCursorAdapter extends CursorAdapter {

private static final int DIFFICULT = 0;
private static final int FAMILIAR = 1;
private static final int EASY = 2;
private static final int PERFECT = 3;

public VocabCursorAdapter(Context context, Cursor c, int flags) {
    super(context, c, 0);
}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
    return LayoutInflater.from(context).inflate(R.layout.item_vocab, parent, false);
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    // Find fields to populate in inflated template
    TextView tvVocabName = (TextView) view.findViewById(R.id.vocabName);
    TextView tvVocabDefinition = (TextView) view.findViewById(R.id.vocabDefinition);
    ImageView tvVocabLevel = (ImageView) view.findViewById(R.id.vocabLevel);
    // Extract properties from cursor
    String vocab = cursor.getString(cursor.getColumnIndexOrThrow(VocabDbContract.COLUMN_NAME_VOCAB));
    String definition = cursor.getString(cursor.getColumnIndexOrThrow(VocabDbContract.COLUMN_NAME_DEFINITION));
    int level = cursor.getInt(cursor.getColumnIndexOrThrow(VocabDbContract.COLUMN_NAME_LEVEL));
    // Populate fields with extracted properties
    tvVocabName.setText(vocab);
    tvVocabDefinition.setText(definition);

    if (level == DIFFICULT) {
        tvVocabLevel.setImageResource(R.drawable.level_bars_difficult);
        tvVocabLevel.setTag(DIFFICULT);
    }
    else if (level == FAMILIAR) {
        tvVocabLevel.setImageResource(R.drawable.level_bars_familiar);
        tvVocabLevel.setTag(FAMILIAR);
    }
    else if (level == EASY) {
        tvVocabLevel.setImageResource(R.drawable.level_bars_easy);
        tvVocabLevel.setTag(EASY);
    }
    else if (level == PERFECT) {
        tvVocabLevel.setImageResource(R.drawable.level_bars_perfect);
        tvVocabLevel.setTag(PERFECT);
    }
}

And here's my list item xml, item_vocab.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:longClickable="true">

<ImageView
    android:layout_width="36sp"
    android:layout_height="36sp"
    android:id="@+id/vocabLevel"
    android:layout_gravity="right"
    android:src="@drawable/level_bars"
    android:scaleType="fitXY"
    android:contentDescription="@string/vocab_level"
    android:layout_centerVertical="true"
    android:layout_toLeftOf="@+id/editCheckbox"
    android:layout_toStartOf="@+id/editCheckbox"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="Large Text"
    android:id="@+id/vocabName"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_toLeftOf="@+id/vocabLevel"
    android:layout_toStartOf="@+id/vocabLevel"/>

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceSmall"
    android:text="Small Text"
    android:id="@+id/vocabDefinition"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:layout_toLeftOf="@+id/vocabLevel"
    android:layout_toStartOf="@+id/vocabLevel"
    android:layout_below="@id/vocabName"/>

<CheckBox
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/editCheckbox"
    android:layout_centerVertical="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"/>

</RelativeLayout>

And here's my xml which contains a listview

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".controller.MyVocab"
            android:paddingLeft="5dp">

<ListView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:id="@+id/mVocabList"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"/>

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/empty_text_view"
    android:id="@android:id/empty"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"/>

</RelativeLayout>

I have looked at a lot of different solutions on StackOverflow, but I wasn't able to successfully do it in my own app. For an example, this post has a similar problem, but its solution used getView and I had trouble understanding how to implement it with newView and bindView instead.

And some other solutions might be examples where a cursoradapter is not involved. Any help is much appreciated, thanks a lot! Edit #1: After incorporating Phan's changes, the checkbox states get resets to false rather than keeping its states when I scroll the listview (See ).

解决方案

Reason : ListView re-uses the views.

Solution :

class VocabCursorAdapter extends CursorAdapter {
    List<Integer> selectedItemsPositions;//to store all selected items position

    public VocabCursorAdapter(Context context, Cursor c,int flags) {
        super(context, c,0);
        selectedItemsPositions = new ArrayList<>();
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup viewGroup) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_vocab, viewGroup, false);
        CheckBox box = (CheckBox) view.findViewById(R.id.editCheckbox);
        box.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
                int position = (int) compoundButton.getTag();
                if (b) {
                    //check whether its already selected or not
                    if (!selectedItemsPositions.contains(position))
                        selectedItemsPositions.add(position);
                } else {
                    //remove position if unchecked checked item
                    selectedItemsPositions.remove((Object) position);
                }
            }
        });
        return view;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        //your other stuff

        CheckBox box = (CheckBox) view.findViewById(R.id.editCheckbox);
        box.setTag(cursor.getPosition());

        if (selectedItemsPositions.contains(cursor.getPosition()))
            box.setChecked(true);
        else
            box.setChecked(false);
    }
}

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

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