2009-10-01 16 views
43

Próbuję powiązać dane z mojego SQLiteDatabase z ListView. Obecnie używam SimpleCursorAdapter do wypełnienia mojego ListView. Niestety nie działa to przy ustawianiu sprawdzanego atrybutu CheckBox.Android: Wiązanie danych z bazy danych do CheckBox w ListView?

Oto, jak to teraz robię; zamiast zmieniać status sprawdzania CheckBox, adapter wpisuje wartość do argumentu tekstowego, więc wartość jest wyświetlana po prawej stronie CheckBox jako tekst.

Java:

setListAdapter(new SimpleCursorAdapter(this, 
     R.layout.mylist, 
     data, 
     new String[] { Datenbank.DB_STATE, Datenbank.DB_NAME }, 
     new int[] { R.id.list_checkbox, R.id.list_text } 
    )); 

mylist.xml:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout android:id="@+id/LinearLayout01" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
xmlns:android="http://schemas.android.com/apk/res/android" 
> 

<CheckBox android:text="" 
    android:id="@+id/list_checkbox" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:checked="false" 
    ></CheckBox> 

<TextView android:text="" 
    android:id="@+id/list_text" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    ></TextView> 

</LinearLayout> 

Edit: Pole w bazie danych jest oczywiście typu boolean i próbowałem również przypisać identyfikator do sprawdzonej pole do wypełnienia wartości.

Odpowiedz

33

Nie jestem pewien, w jaki sposób można to zrobić poza utworzeniem niestandardowej karty, która przeszła w tryb newView/bindView lub getView, w zależności od tego, co można przesłonić (ResourceCursorAda pter jest dobry).

OK, więc oto przykład. I nie sprawdzać, czy to skompilować, bo jestem w pracy, ale to zdecydowanie powinien skierować Cię w dobrym kierunku:

public class MyActivity extends ListActivity { 

    MyAdapter mListAdapter; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     Cursor myCur = null; 

     myCur = do_stuff_here_to_obtain_a_cursor_of_query_results(); 

     mListAdapter = new MyAdapter(MyActivity.this, myCur); 
     setListAdapter(mListAdapter); 
    } 


    private class MyAdapter extends ResourceCursorAdapter { 

     public MyAdapter(Context context, Cursor cur) { 
      super(context, R.layout.mylist, cur); 
     } 

     @Override 
     public View newView(Context context, Cursor cur, ViewGroup parent) { 
      LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      return li.inflate(R.layout.mylist, parent, false); 
     } 

     @Override 
     public void bindView(View view, Context context, Cursor cur) { 
      TextView tvListText = (TextView)view.findViewById(R.id.list_text); 
      CheckBox cbListCheck = (CheckBox)view.findViewById(R.id.list_checkbox); 

      tvListText.setText(cur.getString(cur.getColumnIndex(Datenbank.DB_NAME))); 
      cbListCheck.setChecked((cur.getInt(cur.getColumnIndex(Datenbank.DB_STATE))==0? false:true)))); 
     } 
    } 
} 
+0

Czy możesz dać mi przykład, ponieważ jestem naprawdę nowy w programowaniu Androida i nie widziałem jeszcze czegoś takiego? – svens

+0

Jasne, lemie coś wykopcie, a ja to opublikuję. – MattC

+0

Dzięki! Zadziałało. Wydaje się, że nie ma funkcji getBoolean(); teraz używam cbListCheck.setChecked ((cur.getInt (cur.getColumnIndex (Datenbank.DB_STATE)) == 0? False: true)); który załatwia sprawę. – svens

38

Można ustawić niestandardowy SimpleCursorAdapter.ViewBinder:

SimpleCursorAdapter cursorAdapter = new SimpleCursorAdapter(/* ur stuff */); 
cursorAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() { 
    public boolean setViewValue(View view, Cursor cursor, int columnIndex) { 
     if(columnIndex == 1) { 
      CheckBox cb = (CheckBox) view; 
      cb.setChecked(cursor.getInt(1) > 0); 
      return true; 
     } 
     return false; 
    } 
}); 

Metoda setViewValue jest wywoływana dla każdej kolumny określonej w konstruktorze SimpleCursorAdapter i zapewnia dobre miejsce do manipulowania niektórymi (lub wszystkimi) widokami.

+3

Jedynym problemem jest to, że nie jest to możliwe na poziomie aplikacji 3 (Android 1.5). Jest to dostępne na poziomie aplikacji APi na poziomie 5. –

+1

Ta technika bardzo dobrze mi pomogła w załadowaniu obrazów do widoku listy. Dzięki. –

+4

Dokumenty mówią, że są dostępne od poziomu API 1. Również bezpieczne jest kierowanie na poziom 5 i wyższy: http://developer.android.com/resources/dashboard/platform-versions.html – plainjimbo

0

Można rozwiązać ten problem poprzez tworzenie niestandardowych widget CheckBox tak:

package com.example.CustomCheckBox;  
public class CustomCheckBox extends CheckBox { 
    public CustomCheckBox(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 
    public CustomCheckBox(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 
    public CustomCheckBox(Context context) { 
     super(context); 
    } 
    protected void onTextChanged(CharSequence text, int start, int before, int after) { 
     if (text.toString().compareTo("") != 0) { 
     setChecked(text.toString().compareTo("1") == 0 ? true : false); 
     setText(""); 
     } 
    } 
    } 

Funkcja onTextChanged zostanie wywołana gdy ListView wiąże dane do CheckBox (tj Dodanie albo „0” lub ". 1 "). Spowoduje to wychwycenie tej zmiany i dodanie przetwarzania boolowskiego. Pierwsze wyrażenie "jeśli" jest potrzebne, aby nie tworzyć nieskończonej rekursji.

Następnie podać swoje niestandardowej klasy do pliku jako taki układ:

<com.example.CustomCheckBox 
android:id="@+id/rowCheckBox" 
android:layout_height="fill_parent" 
android:layout_width="wrap_content" /> 

To powinno wystarczyć!

+0

Podoba mi się ta implementacja najlepiej, jednak gdy go wypróbuję, mój program ulega awarii, gdy próbuje nadmuchać mój obiekt CustomCheckBox. Dlaczego miałoby to być? – finiteloop

+0

To rozwiązanie nie działa dla mnie. – petrnohejl

Powiązane problemy