IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants graphiques Android Discussion :

ListView avec checkbox et adapter


Sujet :

Composants graphiques Android

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 54
    Points : 33
    Points
    33
    Par défaut ListView avec checkbox et adapter
    Bonjour, je commence à développé sous Android et je suis bloqué sur un cas tordu.

    Contexte : j'ai une ListActivity avec un champ EditText, un Button, et une ListView. La liste contient deux champs texte et une checkbox. J'ai créé une classe basée sur un SimpleCursorAdapter pour gérer le contenu de la liste, et aussi pour intercepter le changement d'état du checkbox.

    Problème : lorsque je clique sur le checkbox (dans la liste) je met à jour la base de données (pour mémoriser le statut de l'enregistrement). Et je souhaite ensuite mettre à jour le curseur de l'adapter dans le but d'afficher ma liste convenablement (lors de l'affichage du clavier virtuel par exemple). Et le problème se produit ici... ça ne marche pas comme je voudrais.

    Détail : en appelant notifyDataSetChanged il régénère un évènement onCheckedChanged. C'est comme si j'avais cliqué de nouveau sur le checkbox. En plus il n'affiche plus correctement les lignes (avec remplacement d'un élément par un autre).

    J'ai placé deux screens dans les pièces jointes. Le premier correspond à mon écran au démarrage (affichage des produits A,B,C,D), le deuxième correspond à mon écran après un clic sur la checkbox du "Produit B". La liste affiche alors les produits A,B,A,D...

    Vous trouverez si dessous le code qui me permet d'initialiser ma liste :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    public void initListView() {
    		Cursor cursor = null;
     
    		try {
    			setListAdapter(null);
    			cursor = dbh.fetchAllObject(idcaddee,"name asc");
        		if(cursor != null) {
        			if(cursor.moveToFirst()) {
    	    			startManagingCursor(cursor);
    	    			ObjectListCursorAdapter adpater = new ObjectListCursorAdapter(this, R.layout.detail_listview, cursor,
    						new String[] {"name"}, new int[] {R.id.name});    			
    	    			setListAdapter(adpater);
        			}
        		}
        	}
        	catch(Exception e){
                e.printStackTrace();
            }
    }
    Et ici le code de ma classe adapter (avec interception événement checkbox):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    public class ObjectListCursorAdapter extends SimpleCursorAdapter implements OnCheckedChangeListener {
     
    	private DataBaseHelper dbh;
    	private int layout;
     
    	public ObjectListCursorAdapter(Context context, int layout, Cursor c,
    			String[] from, int[] to) {
    		super(context, layout, c, from, to);
    		this.layout = layout;
    		this.dbh = new DataBaseHelper(context);
    		this.dbh.open();
    	}
     
    	@Override
    	public View newView(Context context, Cursor cursor, ViewGroup parent) {
    	    final LayoutInflater inflater = LayoutInflater.from(context);
    	    View v = inflater.inflate(layout, parent, false);
    	    ViewHolder holder = new ViewHolder(v);
    	    v.setTag(holder);		
    	    bindView(v, context, cursor);    
    		holder.getCbStatus().setOnCheckedChangeListener(this);
    	    return v;
    	}
     
    	@Override
    	public void bindView(View v, Context context, Cursor c) {
    	    ViewHolder holder = (ViewHolder)v.getTag();
    	    TextView tv = null;
    	    CheckBox cb = null;
     
    	    if((cb = holder.getCbStatus()) != null) {
    	    	cb.setChecked(c.getInt(c.getColumnIndex("status")) == 1 ?
        			true : false);
    	    	cb.setTag(c.getLong(c.getColumnIndex("_id")));
    	    }
     
    	    if((tv = holder.getName()) != null) {
    	        tv.setText(c.getString(c.getColumnIndex("name")));
    	    }
     
    	    if((tv = holder.getComment()) != null) {
    	    	tv.setText(
    	    		c.getString(c.getColumnIndex("quantity"))+" "+
    	    		c.getString(c.getColumnIndex("unity")));
    	    }
    	}
     
    	public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
     
    		try{
    			if(buttonView.isPressed() == true) {
    				ContentValues values = new ContentValues();
    				values.put("status",isChecked == true ? 1:0);
    				long rowid = (Long) buttonView.getTag(); 
    				dbh.updateObject(rowid,values);
    				this.notifyDataSetChanged();
    			}
    		}
    		catch(Exception e){
    	        e.printStackTrace();
    	    }
    	}
    }
    Images attachées Images attachées   

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 54
    Points : 33
    Points
    33
    Par défaut
    J'ai un complément d'informations après avoir debug le programme. En fait, après l'appel de notifyDataSetChanged je repasse dans la fonction bindView pour chacun des enregistrements.

    Je constate que j'ai un déphasage entre le curseur et ma vue. Et comme j'ai un déphasage, je repasse dans la fonction onCheckedChanged ce qui refait un notifyDataSetChanged. Bref, je tourne en rond...

    Le déphasage est créé de la manière suivante (exemple sur trois enregistrements) : il récupère le pointeur de la troisième vue avec le curseur pointant sur le premier enregistrement... euh comment faire ?

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 54
    Points : 33
    Points
    33
    Par défaut
    Je viens d'implémenter mon adapter avec getView(). Je constate que sur un notifyDataSetChange, il parcours les vues à l'envers avec la position "normale". C'est comme s'il perdait le lien vue/position ou vue/curseur.

    Comment faire ?

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 54
    Points : 33
    Points
    33
    Par défaut CustomAdapter : déphasage entre view et position
    J'ai créé une classe basé sur SimpleCursorAdapter. Sur l’évènement onCheckedChanged, je met à jour ma BDD et j'exécute la commande suivante : notifyDataSetChanged.

    Je constate que ma classe parcourt les vues à l'envers (ordre inverse de l'ordre de création) mais avec les positions d'origine. Je m'explique via un schéma :

    Au lancement, création des vues :

    Vue A : position 0
    Vue B : position 1
    Vue C : position 2

    Après un clic sur un checkbox :

    Vue C : position 0
    Vue B : position 1
    Vue A : position 2

    Comment expliquer cela ? Que faut il faire pour ne pas avoir de déphasage.

    PS : post relatif : http://www.developpez.net/forums/d10...ckbox-adapter/

  5. #5
    Expert éminent

    Avatar de Feanorin
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    4 589
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 4 589
    Points : 9 149
    Points
    9 149
    Par défaut
    Bonjour,

    Essaye plutôt avec un requery() sur ton Cursor au lieu d'un notifydatachanged().
    Responsable Android de Developpez.com (Twitter et Facebook)
    Besoin d"un article/tutoriel/cours sur Android, consulter la page cours
    N'hésitez pas à consulter la FAQ Android et à poser vos questions sur les forums d'entraide mobile d'Android.

Discussions similaires

  1. WPF ListView avec Checkbox, trouver l'item qui a été Checked
    Par fmadore dans le forum Windows Presentation Foundation
    Réponses: 4
    Dernier message: 09/12/2008, 17h21
  2. [VB.NET] Problème ListView avec checkbox
    Par elkidos dans le forum Windows Forms
    Réponses: 1
    Dernier message: 15/02/2007, 15h27
  3. Listview avec checkboxes (récupérer cocher)
    Par Ardely dans le forum Delphi
    Réponses: 3
    Dernier message: 08/01/2007, 17h01
  4. [VB.NET] Listview avec checkboxes
    Par Tiib_CD dans le forum Windows Forms
    Réponses: 8
    Dernier message: 05/12/2006, 09h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo