CheckBox автоматически проверяется в ListView при прокрутке списка

Я использую ListView в своем приложении, которое содержит некоторые элементы, такие как текстовые поля и CheckBox в каждом элементе списка. Когда я заполняю первое текстовое поле, седьмое или любое другое текстовое поле автоматически заполняется одним и тем же значением, и то же самое происходит с CheckBox, когда я проверил CheckBox любой другой случайный CheckBox также отмечается автоматически.

Я не могу понять, почему это происходит.

Мой код ниже:

Список содержимого

<!--- add your MY problem code comment -->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/hyList"
    android:layout_width="fill_parent"
    android:layout_height="35sp"
    android:layout_gravity="top"
    android:orientation="horizontal" >

    <TableLayout
        android:id="@+id/tbltab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="100" >    
        <TableRow
            android:id="@+id/rowfooter"
            android:layout_width="fill_parent"
            android:layout_height="35sp"
            android:gravity="center_horizontal|bottom" >    
            <TextView
                android:id="@+id/txt_Hy_ID"
                android:layout_width="0sp"
                android:layout_height="35sp"
                android:textSize="1pt" >
            </TextView>    
            <TextView
                android:id="@+id/txt_HyID"
                android:layout_width="0sp"
                android:layout_height="35sp"
                android:textSize="1pt" >
            </TextView>    
            <TextView
                android:id="@+id/txt_Hy_Area"
                android:layout_width="200sp"
                android:layout_height="35sp"
                android:layout_gravity="center_vertical"
                android:gravity="left"
                android:textSize="8pt" >
            </TextView>    
            <CheckBox
                android:id="@+id/chkHyCondition"
                android:layout_width="60sp"
                android:layout_height="35sp"
                android:layout_gravity="center"
                android:saveEnabled="true" />    
            <EditText
                android:id="@+id/editTxtHyRemarks"
                android:layout_width="120sp"
                android:layout_height="35sp"
                android:layout_gravity="center_vertical|left"
                android:gravity="center_vertical|left"
                android:maxLength="25"
                android:saveEnabled="true"
                android:textSize="8pt" >
            </EditText>
        </TableRow>
    </TableLayout>    
</LinearLayout>

и список

<ListView
   android:id="@+id/ListViewHy"
   android:layout_width="420sp"
   android:layout_height="100sp"
   android:layout_column="0"
   android:layout_span="3"
   android:clickable="true"
   android:saveEnabled="true"
   android:scrollbarSize="10sp"
   android:scrollbars="vertical" >
   </ListView>

Я использую это для привязки моего списка:

private void FillGridHygiene() {
    LstViewHy = (ListView) findViewById(R.id.ListViewHy);
    clsDatabase dbh = new clsDatabase(this);
    dbh.openDataBase();
    Cursor cursor;
    cursor = dbh.getGridData("030");
    dbh.close();
    if (cursor != null) {
        int cnt = cursor.getCount();
        if (cnt > 0) {
            startManagingCursor(cursor);
            try {
                // -----------BindingListView----------------------------------------------------------------------------

                SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
                        R.layout.hygiene_list, cursor, new String[] {
                                Audit_FSD_Tab.KEY_ROW_ID,
                                Audit_FSD_Tab.KEY_ID,
                                Audit_FSD_Tab.KEY_SHORT_NAME }, new int[] {
                                R.id.txt_Hy_ID, R.id.txt_HyID,
                                R.id.txt_Hy_Area });
                adapter.setViewResource(R.layout.hygiene_list);
                LstViewHy.setAdapter(adapter);
                LstViewHy.setTextFilterEnabled(true);
                LstViewHy.setFocusable(false);
                LstViewHy.setVisibility(View.VISIBLE);

            } catch (Exception ex) {
                ex.fillInStackTrace();
            }
        }

    }
}

Изменить :1

Уровень API — версия 7 — 2.1


person Community    schedule 19.04.2012    source источник
comment
listview перерабатывает свое представление. вы должны использовать свой собственный адаптер   -  person Zaz Gmy    schedule 23.04.2012
comment
Спасибо, но не могли бы вы подсказать мне, как я могу этого добиться?   -  person Trikaldarshiii    schedule 23.04.2012
comment
см. эти thinkandroid.wordpress.com/2010/01/11/custom-cursoradapters , blog.cluepusher.dk/2009/11/16/   -  person Zaz Gmy    schedule 23.04.2012


Ответы (2)


Проблема в дизайне вашего списка. Вам нужно создать пользовательский адаптер и с помощью держателя представления и конвертировать представление повторно использовать ваши представления. Просмотр списка Просмотр списка с использованием базового адаптера

Это поможет вам понять концепцию ListView и даст представление о том, почему другое случайное текстовое поле автоматически заполняется тем же значением, и то же самое происходит с флажком, когда я установил флажок, любой другой случайный флажок также устанавливается автоматически. Надеюсь, это поможет вам и поможет в разработке вашего списка.

person Arun    schedule 18.05.2012
comment
держатель вида недоступен для 2.1 - person Trikaldarshiii; 18.05.2012
comment
ViewHolder — это определяемый пользователем класс. Это не Android-зависимый класс - person Arun; 18.05.2012

Как сказал другой, вам нужно будет создать собственный Adapter и правильно установить/восстановить значения (для CheckBox/EditText) для каждой строки в bindView. Ниже приведен простой пример Adapter, в котором хранится состояние:

public class CustomAdapter extends SimpleCursorAdapter {

            // this will hold a mapping between the row ids and a special object that  will store the values for the EditText and CheckBox
    private HashMap<Long, StateSaver> status = new HashMap<Long, StateSaver>();

    public CustomAdapter(Context context, int layout, Cursor c,
            String[] from, int[] to) {
        super(context, layout, c, from, to);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        super.bindView(view, context, cursor);
                    // get th id of the this row so we can use it as an identifier
        long theId = cursor.getLong(cursor.getColumnIndex("_id"));
        CheckBox ckb = (CheckBox) view.findViewById(R.id.checkBox1);
        ckb.setTag(new Long(theId));
                    // store the status of the CheckBox when it changes
        ckb.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            @Override
            public void onCheckedChanged(CompoundButton buttonView,
                    boolean isChecked) {
                Long theRealId = (Long) buttonView.getTag();
                StateSaver obj = status.get(theRealId);
                if (obj == null) {
                    obj = new StateSaver();
                    status.put(theRealId, obj);
                }
                obj.checked = isChecked;
            }
        });
        EditText et = (EditText) view.findViewById(R.id.editText1);
        et.setTag(new Long(theId));
                    // when the EditText losses focus it's time to store the value entered by the user
        et.setOnFocusChangeListener(new OnFocusChangeListener() {

            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                if(!hasFocus) {
                    Long theRealId = (Long) v.getTag();
                    StateSaver obj = status.get(theRealId);
                    if (obj == null) {
                        obj = new StateSaver();
                        status.put(theRealId, obj);
                    }
                    obj.currentInput = ((EditText) v).getText().toString();
                }
            }
        });
        StateSaver sv = status.get(theId);
        // setup the row with the correct data, either the default or what you've previously stored
        if (sv == null) {
            ckb.setChecked(false);
            et.setText("");
        } else {
            ckb.setChecked(sv.checked);
            et.setText(sv.currentInput);
        }

    }

    private class StateSaver {
        boolean checked = false;
        String currentInput = "";
    }

}

Также вам нужно установить android:windowSoftInputMode="adjustPan" для Activity, содержащего ListView.

Мой совет: избегайте использования EditText в строке ListView. Кроме того, попытайтесь улучшить макет строки: sp единиц следует использовать только для размеров текста (используйте dp вместо любых других мест), не используйте pt единиц, посмотрите, действительно ли вам нужен атрибут layout_weight и т. д.

person user    schedule 18.05.2012