List view with simple cursor adapter items checked are un-checked during scroll

给你一囗甜甜゛ 提交于 2020-01-21 21:21:45

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!