43 votes

Android : Lier des données d'une base de données à une CheckBox dans une ListView ?

J'essaye de lier les données de mes SQLiteDatabase à un ListView . J'utilise actuellement un SimpleCursorAdapter pour remplir mon ListView . Malheureusement, cela ne semble pas fonctionner avec la définition de l'attribut checked d'une CheckBox.

Voici comment je procède maintenant : au lieu de modifier l'état coché de la case à cocher, l'adaptateur remplit la valeur de l'argument texte, de sorte que la valeur s'affiche à droite de la case à cocher sous forme de texte.

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 : Le champ dans la base de données est bien sûr de type booléen et j'ai également essayé d'attribuer un id au champ coché pour remplir la valeur.

37voto

Josef Pfleger Points 37003

Vous pourriez définir un 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;
    }
});

En setViewValue est invoquée pour chaque colonne que vous spécifiez dans le champ SimpleCursorAdapter et vous donne un bon endroit pour manipuler une partie (ou la totalité) des vues.

3 votes

Le seul problème est qu'il n'est pas disponible au niveau 3 de l'api (Android 1.5). Elle est disponible à partir du niveau 5 de l'API.

1 votes

Cette technique a très bien fonctionné pour moi afin d'obtenir des images chargées dans une vue en liste. Merci.

4 votes

Les documents disent qu'ils sont disponibles depuis le niveau 1 de l'API. Aussi, il devrait être assez sûr de cibler le niveau 5 et plus maintenant : developer.Android.com/resources/dashboard/

33voto

MattC Points 8392

Je ne suis pas sûr de la façon dont vous pourriez le faire, à part en créant un adaptateur personnalisé qui surcharge newView/bindView ou getView, selon ce que vous surchargez (ResourceCursorAdapter en est un bon).

Ok, alors voici un exemple. Je n'ai pas testé pour voir s'il compile parce que je suis au travail, mais cela devrait vous mettre sur la bonne voie :

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 votes

Pourriez-vous me donner un exemple, car je suis vraiment nouveau dans la programmation Android et je n'ai pas encore vu quelque chose comme ça ?

0 votes

Bien sûr, laisse-moi trouver quelque chose et je le posterai.

0 votes

Merci ! ! Cela a fonctionné. Il semble qu'il n'y ait pas de fonction getBoolean() ;-) . J'utilise maintenant cbListCheck.setChecked( (cur.getInt(cur.getColumnIndex(Datenbank.DB_STATE))==0 ? false:true) ) ; ce qui fait l'affaire.

0voto

Nick Points 1

Vous pouvez résoudre ce problème en créant un widget CheckBox personnalisé comme suit :

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("");
      }
     }
    }

La fonction onTextChanged sera appelée lorsque le ListView liera les données à la case à cocher (c'est-à-dire en ajoutant soit "0" soit "1"). Cela permettra d'attraper ce changement et d'ajouter votre traitement booléen. La première instruction "if" est nécessaire pour ne pas créer une récursion infinie.

Ensuite, fournissez votre classe personnalisée dans le fichier de mise en page comme tel :

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

Ça devrait le faire !

0 votes

Je préfère cette implémentation, mais lorsque je l'essaie, mon programme se bloque lorsqu'il tente de gonfler mon objet CustomCheckBox. Comment cela se fait-il ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X