问题
I have problem that I couldn't find answer on SO - all problems solved on SO where about too much different issue and didn't work.
Problem is -
1. Clicked rows in ListView (after click they are marked with blue coolor background, and checked box) loose their marks of beeing clicked (checked checkbox and color) after scrolling.
2. Even more - other rows are marked during scroll even that are not clicked.
ListView is bound to my Custom Simple Cursor Adapter which gets data from SQLite database.
Each row of listview has many columns with textboxes and one checkbox - so default multiple choice mode selection in ListView doesn't work in my case - I use onItemClick to get selected items. In ListView Activity I handle checked items on my own in a list.
ListView is also in a HorizontalScrollView.
So these are my classes and layouts:
MyListActivity
public class MyListActivity extends ListActivity
{ .....
public void initComponents()
{
baza = dbMan.openDB(true);
cursorListaFaktur = wyswietlWszystkieTowary();
startManagingCursor(cursorListaFaktur);
fakturyLista = this.getListView();
fakturyLista.setScrollContainer(true);
fakturyLista.setScrollingCacheEnabled(true);
fakturyLista.setItemsCanFocus(false);
fakturyLista.setTextFilterEnabled(true);
fakturyLista.setItemChecked(0, true);
String[] columns = new String[] { "NRDOK", "NAZWADOK", "ANULOWANY",
"NAZWASKR", "DATA", "SUMA", "MIEJSCOWOSC", "TERMIN",
"WYEKSPORTOWANY", "MSPRZ_DOKUMENT.UWAGI" };
int[] kontrolki = new int[] { R.id.ID_FakturyRow_NrFakt,
R.id.ID_FakturyRow_Typ, R.id.ID_FakturyRow_Anulowany,
R.id.ID_FakturyRow_DataSprzed,
R.id.ID_FakturyRow_Kontrahent,
R.id.ID_FakturyRow_Suma, R.id.ID_FakturyRow_Miejscowosc,
R.id.ID_FakturyRow_Termin, R.id.ID_FakturyRow_Wyeksp,
R.id.ID_FakturyRow_Uwagi };
String[] columnsRaportKasowy = new String[] { "NRDOK", "NAZWADOK",
"GOTOWKA", "GOTOWKA", "NAZWASKR", "DATA", "UWAGI" };
int[] kontrolkiRaportKasowy = new int[] {
R.id.ID_RaportKasowyRow_NrFakt,
R.id.ID_RaportKasowyRow_Typ,
R.id.ID_RaportKasowyRow_Wplata,
R.id.ID_RaportKasowyRow_Wyplata,
R.id.ID_RaportKasowyRow_Kontrahent,
R.id.ID_RaportKasowyRow_DataSprzed,
R.id.ID_RaportKasowyRow_Uwagi };
if (raportKasowy)
{
adapterFaktury = new MSprzedazRaportKasowyAdapter(this,
R.layout.raportkasowy_row, cursorListaFaktur,
columnsRaportKasowy, kontrolkiRaportKasowy);
}
else
{
adapterFaktury = new
MSprzedazListViewAdapter(this,R.layout.faktury_row,
cursorListaFaktur, columns, kontrolki);
}
fakturyLista.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3)
{
LinearLayout linLay = (LinearLayout) arg1;
ArrayList<View> kontrolki = arg1.getTouchables();
CheckBox chBox = (CheckBox) kontrolki.get(0);
chBox.setChecked(!chBox.isChecked());
Cursor cursor = adapterFaktury.getCursor();
cursor.moveToPosition(arg2);
String tekstKom = "";
if(MSprzedazUtils.znajdzIdWliscieZazn(
cursor.getInt(cursor.getColumnIndex("_id"))
, listaZaznaczonych) == null)
{
listaZaznaczonych.add(cursor.getInt(cursor.getColumnIndex("_id")));
linLay.setBackgroundColor(Color.rgb(110, 151, 186));
MSprzedazUtils.wpisDoLoga(tekstKom);
}
else
{
try
{
listaZaznaczonych.remove((int)
MSprzedazUtils.znajdzIdWliscieZazn(
cursor.getInt(cursor.getColumnIndex("_id")),
listaZaznaczonych));
MSprzedazUtils.wpisDoLoga(tekstKom);
}
catch(IndexOutOfBoundsException ex)
{
MSprzedazUtils.wpisDoLoga("Błąd"+tekstKom);
}
}
}
});
MySimpleCursorAdapter
public class MySimpleCursorAdapter extends SimpleCursorAdapter
{
class ViewHolder
{
CheckBox chckBoxZazn;
LinearLayout linLay;
TextView nrDok;
TextView typDok;
boolean isSelected;
TextView txtData;
TextView txtKontrahent;
TextView txtSuma;
TextView txtAnulowany;
TextView txtMiejscowosc;
TextView txtTermin;
TextView txtWyeksp;
TextView txtUwagi;
}
@Override
public void bindView(View convertView, Context context, Cursor cursor)
{
if (convertView.getTag() != null)
holder = (ViewHolder) convertView.getTag();
{
// holder.linLay = (LinearLayout)convertView;
holder.chckBoxZazn = (CheckBox) convertView.findViewById(R.id.ID_FakturyRow_ChckBoxFakturyWybor);
holder.nrDok = (TextView) convertView.findViewById(R.id.ID_FakturyRow_NrFakt);
holder.typDok = (TextView) convertView.findViewById(R.id.ID_FakturyRow_Typ);
holder.txtAnulowany = (TextView) convertView.findViewById(R.id.ID_FakturyRow_Anulowany);
holder.txtData = (TextView) convertView.findViewById(R.id.ID_FakturyRow_Kontrahent);
holder.txtKontrahent = (TextView) convertView.findViewById(R.id.ID_FakturyRow_DataSprzed);
holder.txtMiejscowosc = (TextView) convertView.findViewById(R.id.ID_FakturyRow_Miejscowosc);
holder.txtSuma = (TextView) convertView.findViewById(R.id.ID_FakturyRow_Suma);
holder.txtTermin = (TextView) convertView.findViewById(R.id.ID_FakturyRow_Termin);
holder.txtWyeksp = (TextView) convertView.findViewById(R.id.ID_FakturyRow_Wyeksp);
holder.txtUwagi = (TextView) convertView.findViewById(R.id.ID_FakturyRow_Uwagi);
}
holder.chckBoxZazn.setTag(cursor.getPosition());
holder.nrDok.setText(cursor.getString(cursor.getColumnIndex("NRDOK")));
holder.typDok.setText(cursor.getString(cursor.getColumnIndex("NAZWADOK")));
if (cursor.getString(cursor.getColumnIndex("DATA")) != null)
holder.txtData.setText(cursor.getString(cursor.getColumnIndex("DATA")).substring(0, 10));
else
holder.txtData.setText("-");
if (cursor.getInt(cursor.getColumnIndex("ANULOWANY")) == 0)
holder.txtAnulowany.setText("NIE");
else
holder.txtAnulowany.setText("TAK");
if (cursor.getString(cursor.getColumnIndex("NAZWASKR")) != null)
holder.txtKontrahent.setText(cursor.getString(cursor.getColumnIndex("NAZWASKR")));
else
holder.txtKontrahent.setText("-");
if (cursor.getString(cursor.getColumnIndex("MIEJSCOWOSC")) != null)
holder.txtMiejscowosc.setText(cursor.getString(cursor.getColumnIndex("MIEJSCOWOSC")));
else
holder.txtMiejscowosc.setText("-");
holder.txtSuma.setText(cursor.getString(cursor.getColumnIndex("SUMA")));
if (cursor.getInt(cursor.getColumnIndex("WYEKSPORTOWANY")) == 0)
{
holder.txtWyeksp.setText("NIE");
holder.txtWyeksp.setBackgroundColor(Color.BLACK);
}
else
{
holder.txtWyeksp.setText("TAK");
convertView.setBackgroundColor(Color.DKGRAY);
}
if (cursor.getString(cursor.getColumnIndex("TERMIN")) != null)
holder.txtTermin.setText(cursor.getString(cursor.getColumnIndex("TERMIN")).substring(0, 10));
else
holder.txtTermin.setText("-");
holder.txtUwagi.setText(cursor.getString(cursor.getColumnIndex("UWAGI")));
if (cursor.getCount() > 0 && cursor.getPosition() < cursor.getColumnCount())
holder.chckBoxZazn.setChecked(jestZaznaczony[cursor.getPosition()]);
}
@Override
public void onClick(View v)
{
if (v.isFocusable())
{
jestZaznaczony[cursor.getPosition()] = !jestZaznaczony[cursor.getPosition()];
holder.chckBoxZazn.setChecked(jestZaznaczony[cursor.getPosition()]);
}
}
}
listview_row.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ID_FakturyRow_KontrRow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<CheckBox
android:id="@+id/ID_FakturyRow_ChckBoxFakturyWybor"
android:layout_width="30dp"
android:layout_height="30dp"
android:focusable="false"
android:focusableInTouchMode="false"
android:text=""
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="10dp"
true="" />
<TextView
android:id="@+id/ID_FakturyRow_NrFakt"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginRight="5dp"
android:focusable="false"
android:maxLength="10"
android:maxLines="1"
android:text="NrFakt"
android:textAppearance="?android:attr/textAppearanceSmall"
true="" />
<TextView
android:id="@+id/ID_FakturyRow_Typ"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginRight="5dp"
android:focusable="false"
android:maxLength="4"
android:maxLines="1"
android:text="Typ"
android:textAppearance="?android:attr/textAppearanceSmall"
true="" />
<TextView
android:id="@+id/ID_FakturyRow_Anulowany"
android:layout_width="46dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
android:maxLength="8"
android:maxLines="1"
android:text="Anulowany"
android:textAppearance="?android:attr/textAppearanceSmall"
android:focusable="false" />
<TextView
android:id="@+id/ID_FakturyRow_Kontrahent"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginRight="10dp"
android:maxLength="14"
android:maxLines="1"
android:text="Kontrahent"
android:focusable="false"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/ID_FakturyRow_DataSprzed"
android:layout_width="120dp"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginRight="10dp"
android:text="Data"
android:focusable="false"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/ID_FakturyRow_Suma"
android:layout_width="65dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="0dp"
android:maxLines="1"
android:text="Suma"
android:focusable="false"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/ID_FakturyRow_Miejscowosc"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="0dp"
android:text="Miejscowosc"
android:focusable="false"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/ID_FakturyRow_Termin"
android:layout_width="75dp"
android:layout_height="wrap_content"
android:layout_marginLeft="35dp"
android:layout_marginRight="25dp"
android:maxLength="18"
android:maxLines="1"
android:text="Termin"
android:focusable="false"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/ID_FakturyRow_Wyeksp"
android:layout_width="70dp"
android:layout_height="wrap_content"
android:layout_marginLeft="35dp"
android:layout_marginRight="0dp"
android:maxLength="16"
android:maxLines="1"
android:text="Wyeksp"
android:focusable="false"
android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/ID_FakturyRow_Uwagi"
android:layout_width="40dp"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="0dp"
android:text="Termin"
android:focusable="false"
android:textAppearance="?android:attr/textAppearanceSmall" />
listview_layout.xml
<HorizontalScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scroller"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginBottom="10dp"
android:fillViewport="true" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ID_FakturyListaButtons_HeaderLayoutWrapper"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="25dp"
android:orientation="vertical" >
....... // Text Views as Listview header
</LinearLayout>
<RelativeLayout
android:id="@+id/ID_FakturyListaButtons_TabListaLayout"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ListView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
</ListView>
</RelativeLayout>
</LinearLayout>
</HorizontalScrollView>
How can I possibly make that ListView with many columns to display ALL and ONLY items that I clicked?
回答1:
This is because Android recycles the rows in the listView. To overcome this, you need to save your row state (checked or not) in some List or something and use this to set a row checked or unchecked. In your getView() function, you can do the following check. Here enabledItems is a List
if (enabledItems.contains(eventTime)) {
viewHolder.getCheckBox().setChecked(true);
} else {
viewHolder.getCheckBox().setChecked(false);
}
Also, have a look at the following article about recycling. http://mobile.cs.fsu.edu/the-nuance-of-android-listview-recycling-for-n00bs/
回答2:
You have to store the checked status yourself, and modify it through your onItemClicked method.
A short example of how the adapter might look with the checked status array:
public class ButtonCursorAdapter extends SimpleCursorAdapter {
private Cursor c;
private Context context;
private Activity activity;
public static int[] chkState;
private int layout;
public ButtonCursorAdapter(Context context, int layout, Cursor c,
String[] from, int[] to) {
super(context, layout, c, from, to);
this.c = c;
this.context = context;
this.activity = (Activity) context;
this.layout = layout;
// create an array to hold checked state, use zero for un-checked and 1 for checked
chkState = new int[c.getCount()]; // Set array size to # of elements in cursor
for(int i=1; i<c.getCount(); i++){ // loop through array
chkState[i] = 0; // set initial state to 0 - not checked
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = View.inflate(context, layout, null);
final int pos = position;
View row = convertView;
c.moveToPosition(position);
// do your data assignement stuff here
// set the state of your checkbox
if (chkState[position] == 0) {
// set the checkbox to checked
} else {
// set the checkbox to unchecked
}
return (row);
}
}
来源:https://stackoverflow.com/questions/12976218/list-view-with-simple-cursor-adapter-items-checked-are-un-checked-during-scroll