Android 使用CursorAdapter在listview中维护复选框状态
对于我的Android项目,我有一个listview,每个项目都有一个复选框。通过使用CursorAdapter类从SQLite数据库加载数据。但是,每当我滚动时,复选框位置都会被移动,并被带到listview的下一部分。我如何解决这个问题? 下面是我的游标适配器类:Android 使用CursorAdapter在listview中维护复选框状态,android,listview,checkbox,android-cursoradapter,android-checkbox,Android,Listview,Checkbox,Android Cursoradapter,Android Checkbox,对于我的Android项目,我有一个listview,每个项目都有一个复选框。通过使用CursorAdapter类从SQLite数据库加载数据。但是,每当我滚动时,复选框位置都会被移动,并被带到listview的下一部分。我如何解决这个问题? 下面是我的游标适配器类: public class VocabCursorAdapter extends CursorAdapter { private static final int DIFFICULT = 0; private static fin
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);
}
}
下面是我的列表项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>
这是我的xml,它包含一个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>
我在StackOverflow上看过很多不同的解决方案,但我无法在自己的应用程序中成功实现。例如,这有一个类似的问题,但它的解决方案使用了getView,我很难理解如何用newView和bindView来实现它
其他一些解决方案可能是不涉及游标适配器的示例。非常感谢您的帮助,非常感谢!
编辑#1:合并Phan的更改后,当我滚动列表视图时,复选框states get resets为false,而不是保留其状态(请参见)。尝试此操作
public class VocabCursorAdapter extends CursorAdapter {
private ArrayList<Boolean> itemChecked = new ArrayList<Boolean>(); // array list for store state of each checkbox
public VocabCursorAdapter(Context context, Cursor c, int flags) {
for (int i = 0; i < c.getCount(); i++) { // c.getCount() return total number of your Cursor
itemChecked.add(i, false); // initializes all items value with false
}
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
...
final int position = cursor.getPosition(); // get position by cursor
CheckBox checkBox = (CheckBox) view.findViewById(R.id.editCheckbox);
checkBox.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (itemChecked.get(position) == true) { // if current checkbox is checked, when you click -> change it to false
itemChecked.set(position, false);
} else {
itemChecked.set(position, true);
}
}
});
checkBox.setChecked(itemChecked.get(position)); // set the checkbox state base on arraylist object state
Log.i("In VocabCursorAdapter","position: "+position+" - checkbox state: "+itemChecked.get(position));
}
}
公共类VocabCursorAdapter扩展了CursorAdapter{
private ArrayList itemChecked=new ArrayList();//每个复选框的存储状态的数组列表
公共词汇库适配器(上下文上下文、游标c、int标志){
对于(int i=0;i将其更改为false
itemChecked.set(位置,false);
}否则{
itemChecked.set(位置,真);
}
}
});
checkBox.setChecked(itemChecked.get(position));//根据arraylist对象状态设置复选框状态
Log.i(“在VocabCursorAdapter中”,“位置:+position+”-复选框状态:+itemChecked.get(位置));
}
}
原因:ListView重新使用视图。解决方案:
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);
}
}
class VocabCursorAdapter扩展了CursorAdapter{
列出selectedItemsPositions;//将所有选定的项目存储到位置
公共词汇库适配器(上下文上下文、游标c、int标志){
super(上下文,c,0);
selectedItemsPositions=newarraylist();
}
@凌驾
公共视图新建视图(上下文上下文、光标、视图组视图组){
视图=LayoutFlater.from(上下文)。充气(R.layout.item_vocab,视图组,false);
复选框=(复选框)view.findViewById(R.id.editCheckbox);
setOnCheckedChangeListener(新的CompoundButton.OnCheckedChangeListener(){
@凌驾
检查更改后的公共无效(复合按钮复合按钮,布尔b){
int position=(int)compoundButton.getTag();
如果(b){
//检查其是否已被选中
如果(!selectedItemsPositions.contains(位置))
选择编辑位置。添加(位置);
}否则{
//如果未选中项目,则删除位置
选择编辑位置。删除((对象)位置);
}
}
});
返回视图;
}
@凌驾
公共void bindView(视图、上下文上下文、光标){
//你的其他东西
复选框=(复选框)view.findViewById(R.id.editCheckbox);
setTag(cursor.getPosition());
if(selectedItemsPositions.contains(cursor.getPosition()))
box.setChecked(true);
其他的
框。setChecked(false);
}
}
公共类观测SelectAttributeFragment扩展片段{
DatabaseHandler mDBHandler;
ListView mListView;
SimpleCursorAdapter mSCA;
Cursor mCsr;
ArrayList<String> attributeItems = new ArrayList<>();
public ObservationselectattributeFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Inflate the layout for this fragment
View view1=inflater.inflate(R.layout.fragment_observationselectattribute, container, false);
//Bundle bundle2 = getArguments();
Bundle bundle1 = getArguments();
final int firsttext= bundle1.getInt("TotalCount");
final String selectedtreatment= bundle1.getString("SelectedTreatment");
Toast.makeText(getActivity(),"value \n"+firsttext+"\n"+"treatment \n"+selectedtreatment, Toast.LENGTH_SHORT).show();
// Toast.makeText(getActivity(),"SelectedTreatment \n"+selectedtreatment, Toast.LENGTH_SHORT).show();
mListView = (ListView)view1.findViewById(R.id.lv001);
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
Button addattribute = (Button)view1.findViewById(R.id.addattribute);
addattribute.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String items1="";
Integer tcount1=0;
for(String item1:attributeItems){
items1+="-"+item1+"\n";
tcount1++;
}
Toast.makeText(getActivity(),"you have selected \n"+items1,Toast.LENGTH_LONG).show();
Toast.makeText(getActivity(),"you have selected \n"+tcount1,Toast.LENGTH_LONG).show();
/*FragmentTransaction fr= getFragmentManager().beginTransaction();
fr.replace(R.id.main_container, new ShowObservationDataRecordingFragment()).addToBackStack("ObservationselectattributeFragment");
fr.commit();*/
Bundle bundle = new Bundle();
bundle.putInt("TotalCount2",firsttext);
bundle.putInt("TotalCount1", tcount1);
bundle.putString("SelectedTreatment", selectedtreatment);
Fragment showobservationdatarecordingfragment = new ShowObservationDataRecordingFragment();
showobservationdatarecordingfragment.setArguments(bundle);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.main_container, showobservationdatarecordingfragment).addToBackStack("ObservationselectattributeFragment").commit();
}
});
mDBHandler = new DatabaseHandler(this.getActivity());
mCsr = mDBHandler.getAllRecords();
// Prepare a list of the columns to get the data from, for the ListViewt
String[] columns_to_get_data_from = new String[]{
DatabaseHandler.KEY_IDS,
DatabaseHandler.KEY_NAMES,
DatabaseHandler.KEY_FNAME,
DatabaseHandler.KEY_MONAME,
DatabaseHandler.KEY_SNAME
};
// Prepare a list of the Views into which to place the data
int[] itemviews_to_place_data_in = new int[]{
R.id.euserid,
R.id.eusername,
R.id.efname,
R.id.emoname,
R.id.esname
};
// get and instance of SimpleCursorAdapter
mSCA = new SimpleCursorAdapter(getActivity(),
R.layout.listviewitem_record,
mCsr,
columns_to_get_data_from,
itemviews_to_place_data_in,
0);
// Save the ListView state (= includes scroll position) as a Parceble
Parcelable state = mListView.onSaveInstanceState();
// get and instance of SimpleCursorAdapter the listviewitem_record layout
mListView.setAdapter(mSCA);
// Restore previous state (including selected item index and scroll position)
mListView.onRestoreInstanceState(state);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String attributeItem1 = ((TextView)view.findViewById(R.id.euserid)).getText().toString();
String attributeItem2 = ((TextView)view.findViewById(R.id.eusername)).getText().toString();
String attributeItem3 = ((TextView)view.findViewById(R.id.efname)).getText().toString();
String attributeItem4 = ((TextView)view.findViewById(R.id.emoname)).getText().toString();
String attributeItem5 = ((TextView)view.findViewById(R.id.esname)).getText().toString();
String attributeItem = attributeItem1 + attributeItem2 + attributeItem3 + attributeItem4 + attributeItem5;
// CheckedTextView box = (CheckedTextView) view.findViewById(R.id.record_checkbox);
// box.setChecked(true);
CheckedTextView checkedTextView = (CheckedTextView) view.findViewById(R.id.record_checkbox);
if(checkedTextView.isChecked()) {
checkedTextView.setChecked(false);
} else {
checkedTextView.setChecked(true);
}
if(attributeItems.contains(attributeItem)){
attributeItems.remove(attributeItem);//uncheck item
}
else
{
attributeItems.add(attributeItem);
}
Toast.makeText(getActivity(), "Item1 = " + attributeItem1 +"\n"+ "Item2 ="+attributeItem2 +"\n"+"Item3 ="+attributeItem3+"\n"+"Item4 ="+attributeItem4+"\n"+"Item5 ="+attributeItem5, Toast.LENGTH_SHORT).show();
}
});
((HomeActivity) getActivity())
.setActionBarTitle("Select Attribute");
return view1;
}
DatabaseHandler-mDBHandler;
列表视图;
简单的mSCA;
光标mCsr;
ArrayList attributeItems=新的ArrayList();
公共观察SelectAttributeFragment(){
//必需的空公共构造函数
}
@凌驾
创建视图上的公共视图(布局、充气机、视图组容器、,
Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//为该碎片膨胀布局
视图1=充气机。充气(R.layout.fragment\u observationselectattribute,container,false);
//Bundle bundle2=getArguments();
Bundle bundle1=getArguments();
final int firsttext=bundle1.getInt(“TotalCount”);
最终字符串selectedtreatment=bundle1.getString(“selectedtreatment”);
Toast.makeText(getActivity(),“value\n”+firsttext+“\n”+“treatment\n”+selectedtreatment,Toast.LENGTH\u SHORT).show();
//Toast.makeText(getActivity(),“SelectedTreatment\n”+SelectedTreatment,Toast.LENGTH\u SHORT).show();
mListView=(ListView)view1.findViewById(R.id.lv001);
mListView.setChoiceMode(ListView.CHOICE\u MODE\u MULTIPLE);
Button addattribute=(Button)view1.findViewById(R.id.addattribute);
addattribute.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图){
字符串items1=“”;
整数tcount1=0;
对于(字符串项1:attributeItems){
项目1+=“-”+项目1+“\n”;
t计数1++;
}
Toast.makeText(getActivity(),“您已选择\n”+items1,Toast.LENGTH\u LONG.show();
Toast.makeText(getActivity(),“您已选择\n”+tcount1,Toast.LENGTH\u LONG.show();
/*FragmentTransaction fr=getFragmentManage