Autore Topic: Multi Choice Dialog, premendo Cancel mi sballa i valori  (Letto 581 volte)

Offline funcool

  • Nuovo arrivato
  • *
  • Post: 42
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Acer Liquid CM 7.1
  • Play Store ID:
    elcasa
  • Sistema operativo:
    Windows 8
Multi Choice Dialog, premendo Cancel mi sballa i valori
« il: 24 Settembre 2011, 20:10:22 CEST »
0
Visto che mi avete già dato una mano.. ci riprovo

Devo usare un semplicissimo Dialog Multi Choice, 7 voci, i giorni della settimana, un array di 7 booleani, ma ho notato un comportamento strano alla pressione di Cancel:

- se un giorno è spuntato, vado a togliere la spunta, premo cancel -> subito dopo richiamo il dialog e il giorno ha il valore corretto, cioè è di nuovo spuntato

- se un giorno NON è spuntato ( false ), vado a mettere la spunta ( true ), premo cancel -> subito dopo richiamo il dialog e il giorno ha valore sbagliato, viene visualizzato come spuntato ( true ) e dando OK lo considera NON spuntato , infatti nell'array lo mette false

questo succede sia con il codice standard google:
Codice (Java): [Seleziona]
case DIALOG_MULTIPLE_CHOICE:
            return new AlertDialog.Builder(this)
                .setTitle("title")
                .setMultiChoiceItems(R.array.weekDays,
                        new boolean[]{false, true, false, true, false, false, false},
                        new DialogInterface.OnMultiChoiceClickListener() {
                            public void onClick(DialogInterface dialog, int whichButton,
                                    boolean isChecked) {
                                /* User clicked on a check box do some stuff */
                            }
                        })
                .setPositiveButton("ok", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        /* User clicked Yes so do some stuff */
                    }
                })
                .setNegativeButton("cancel", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int whichButton) {
                        /* User clicked No so do some stuff */
                    }
                })
               .create();

che con il mio dove ho provato ad usare un array temporaneo e ripristinarlo ai valori precedenti in caso di cancel, ho provato con l'onPrepare, non riesco a far si che ogni volta che si riapre il dialog dopo averlo modificato e aver premuto Cancel abbia i valori corretti di dWeek.getBooleanArray() che è un array di 7 booleani ..
il dialog viene chiamato tramite editDays(), praticamente lo copio sempre 2 volte per niente... prima di fare show( .. ) e nell' onPrepare..
Codice (Java): [Seleziona]
public void editDays(){
       
        System.arraycopy(dWeek.getBooleanArray(), 0, dWeekTmp, 0, 7); // metto nel tmp il valore di dWeek
        showDialog(DIALOG_DAYS_WEEK);
    }
       
        @Override
        protected Dialog onCreateDialog(int id) {
               
                switch (id) {  
                    case DIALOG_DAYS_WEEK:
                        multiChoiceListener = new DialogInterface.OnMultiChoiceClickListener() {
                        /*
                           dialog       The dialog where the selection was made.
                                        which   The position of the item in the list that was clicked.
                                        isChecked       True if the click checked the item, else false.
                       */

                        public void onClick(DialogInterface dialog, int whichButton, boolean isChecked) {
                                // User clicked on a check box do some stuff */
                                // va a modificare automaticamente dWeekTmp
                               
                                //dWeekTmp[whichButton] = isChecked; quindi questo è inutile, giusto ?
                                }
                         };
                       
                        multiChoice = new AlertDialog.Builder(this)
                            .setTitle(R.string.tv_days)
                            .setMultiChoiceItems( R.array.weekDays, dWeekTmp , multiChoiceListener )
                                                        // mi baso su dWeekTmp che ha il valore di dWeek.getBooleanArray()
                            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int whichButton) {
                                    /* User clicked Yes so do some stuff */
                                        // salvo nelle pref
                                       
                                        dWeek = new DaysOfWeek(dWeekTmp);
                                        editor.putString(WEEK_DAYS, dWeek.toString() );
                                        editor.commit();
                                }
                            })
                            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int whichButton) {
                                    // User clicked No so do some stuff
                                        // rimetto in dWeekTmp il valore di dWeek.getBooleanArray(), che è invariato in questo caso ( premuto Cancel )
                                        System.arraycopy(dWeek.getBooleanArray(), 0, dWeekTmp, 0, 7);
                                       
                                }
                            })
                            .create();
                        return multiChoice;
               }
               
               return null;
            }
       
        @Override
        protected void onPrepareDialog(int id, Dialog dialog) {
            switch (id) {
                case DIALOG_DAYS_WEEK:
                                               
                        System.arraycopy(dWeek.getBooleanArray(), 0, dWeekTmp, 0, 7); // metto nel tmp il valore di dWeek
                       
                        multiChoice = new AlertDialog.Builder(this)
                            .setMultiChoiceItems( R.array.weekDays, dWeekTmp , multiChoiceListener ).create();
                        // qui ho provato alla disperata a ri-passargli l'array...
                       break;
                   
                default:
                    break;
            }
        }

avete idea di come fare / cosa sto sbagliando ? in pratica vorrei far si che il dialog parta sempre con i valori dell'array dWeekTmp, visto che in caso di cancel lo ripristino sempre a dWeek.getBooleanArray()

( il dialog lo sto usando da una PreferenceActivity come Preference personalizzata ma non credo sia questo il problema.. )
« Ultima modifica: 25 Settembre 2011, 11:58:21 CEST da funcool »

Offline miroku

  • Nuovo arrivato
  • *
  • Post: 14
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    HTC Tattoo
  • Play Store ID:
    Audero Team
Re:Multi Choice Dialog, premendo Cancel mi sballa i valori
« Risposta #1 il: 26 Settembre 2011, 18:23:37 CEST »
+1
ciao,
dato che hai creato la dialog con il builder, android la conserva in memoria e quindi è inutile che re-imposti dWeekTmp allo stato precedente in quanto android non ricrea la dialog (e quindi non usa più il tuo array dWeekTmp).

Dovresti reimpostare nel negative button ogni checkbox allo stato precedente con il seguente metodo
Codice (Java): [Seleziona]
((AlertDialog) multiChoice ).getListView().setItemChecked(i, vecchio_valore_della_checkbox_i);

buon lavoro  :D

Offline funcool

  • Nuovo arrivato
  • *
  • Post: 42
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Acer Liquid CM 7.1
  • Play Store ID:
    elcasa
  • Sistema operativo:
    Windows 8
Re:Multi Choice Dialog, premendo Cancel mi sballa i valori
« Risposta #2 il: 26 Settembre 2011, 20:46:18 CEST »
0
visti i risultati, immaginavo che il problema fosse una cosa del genere.. appena ho tempo provo, grazie mille intanto !

dato che hai creato la dialog con il builder
c'è un modo migliore ? purtroppo per ora non me ne intendo più di tanto..

ah, un'altra cosa, come potrei fare ad intercettare la pressione del tasto back mentre è visualizzato il dialog ? per dire, una cosa simile:
Codice (Java): [Seleziona]
@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
               
                if ( < dialog multichioce attivo > )
                     <restore vecchi valori>
        }
        return super.onKeyDown(keyCode, event);
    }
« Ultima modifica: 27 Settembre 2011, 10:49:18 CEST da funcool »

Offline miroku

  • Nuovo arrivato
  • *
  • Post: 14
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    HTC Tattoo
  • Play Store ID:
    Audero Team
Re:Multi Choice Dialog, premendo Cancel mi sballa i valori
« Risposta #3 il: 27 Settembre 2011, 12:09:29 CEST »
+1
il metodo alternativo sarebbe quello di creare la dialog custom...solo che devi fare molte più cose di quelle richieste con il builder :D

per il tasto back, non vorrei sbagliare ma quando crei la dialog  con il builder  viene creata con setCancelable(false) quindi il tasto back non viene "ascoltato"

mentre per farlo abilitare devi impostare il
Codice (Java): [Seleziona]
multiChoice.setCancelable(true) inoltre devi implementate onCancelListner
Codice (Java): [Seleziona]
multiChoice.setOnCancelListener(new DialogInterface.OnCancelListener() {
                public void onCancel(DialogInterface dialog) {
                        //quello che vuoi fare
                }
            });

Offline funcool

  • Nuovo arrivato
  • *
  • Post: 42
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Acer Liquid CM 7.1
  • Play Store ID:
    elcasa
  • Sistema operativo:
    Windows 8
Re:Multi Choice Dialog, premendo Cancel mi sballa i valori
« Risposta #4 il: 28 Settembre 2011, 20:48:05 CEST »
0
allora.. non chiedete come e perchè ma funziona, anche se sicuramente è migliorabile...

teoricamente il codice del metodo che mi sistema il dialog  sarebbe dovuto essere questo:
Codice (Java): [Seleziona]
public void restoreDaysMultiChoice(){
                               
        if ( ((AlertDialog) daysMultiChoice ).getListView() != null ) { // nel caso tutti false, l'array è null
                for ( int i=0; i<7;i++){
                        ((AlertDialog) daysMultiChoice ).getListView().setItemChecked(i, dWeekValid[i]);                                       
                }
        }
}

se un giorno NON è spuntato ( false ), vado a mettere la spunta ( true ), premo cancel -> subito dopo richiamo il dialog e il giorno ha valore sbagliato, viene visualizzato come spuntato ( true ) e dando OK lo considera SPUNTATO, infatti nell'array lo mette TRUE , resta il problema dei chek fantasma, nonostante alla chiamata del dialog l'ultimo valore salvato per quel check sia false mi viene visualizzato come true

qui sotto il codice intero, ora il dialog si apre con le spunte sempre corrette, non succede che si apra con spunte che il realtà siano false ecc
Codice (Java): [Seleziona]
public void editDays(){
        showDialog(DIALOG_DAYS_WEEK);
    }
       
        @Override
        protected Dialog onCreateDialog(int id) {
               
                switch (id) {  
                case DIALOG_DAYS_WEEK:
                        System.arraycopy(dWeekValid, 0, dWeekTmp, 0, 7); // metto nel tmp il valore di dWeek
                       
                        daysMultiChoiceListener = new DialogInterface.OnMultiChoiceClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton, boolean isChecked) {
                                // User clicked on a check box do some stuff
                                // va a modificare automaticamente dWeekTmp
                                //dWeekTmp[whichButton] = isChecked; quindi questo è inutile, giusto ?
                                }
                    };
                        daysMultiChoice = new AlertDialog.Builder(this)
                            .setTitle(R.string.tv_days)
                            .setMultiChoiceItems( R.array.weekDays, dWeekTmp , daysMultiChoiceListener )
                                                        // mi baso su dWeekTmp che ha il valore di dWeekValid
                            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int whichButton) {
                                    /* User clicked Yes so do some stuff */                            
                                        System.arraycopy(dWeekTmp , 0,dWeekValid , 0, 7);
                                        tv1.setText( boolArrayToString( dWeekValid ) );                                
                                }
                            })
                            .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, int whichButton) {
                                    // User clicked No so do some stuff
                                        restoreDaysMultiChoice();                              
                                        tv1.setText( boolArrayToString( dWeekValid ) );
                                       
                                }
                            })
                            .setCancelable(true)
                            .setOnCancelListener(new DialogInterface.OnCancelListener() {
                                public void onCancel(DialogInterface dialog) {
                                        restoreDaysMultiChoice();
                                        tv1.setText( boolArrayToString( dWeekValid ) );
                                        }
                                } )
                            .create();
                       
                        return daysMultiChoice;
                                }
               
               
               return null;
            }
       

        public void restoreDaysMultiChoice(){
                               
                if ( ((AlertDialog) daysMultiChoice ).getListView() != null ) { // nel caso tutti false, l'array è null
               
                        for ( int i=0; i<7;i++){
                                //((AlertDialog) daysMultiChoice ).getListView().setItemChecked(i, dWeekValid[i]); // la cosa giusta da fare
                               
                                ((AlertDialog) daysMultiChoice ).getListView().setItemChecked(i, false); // la cosa sbagliata 'egualmente' funzionante
                                               
                        }
               
                        System.arraycopy(dWeekValid, 0, dWeekTmp, 0, 7);  // il solito tentativo alla disperata, che stavolta ha funzionato    
                }
               
        }

insomma l'arraycopy mi risolve il problema riguardante le spunte fantasma, spunte false che se messe vere, premuto cancel e riaperto il dialog mi compaiono come vere

resta una cosa che non capisco, mettendo tutto false ( come nel codice funzionante ) funziona ugualmente e perfettamente.. probabilmente perchè va a ricontrollare dWeekTmp.. sembra quasi faccia un or.. mah

queste prove le ho fatte su una normale activity.. adesso proverò questo dialog sulla preference activity come preference custom e vedremo... ovviamente i suggerimenti sono sempre ben accetti, grazie mille miroku
« Ultima modifica: 29 Settembre 2011, 10:04:47 CEST da funcool »

Offline miroku

  • Nuovo arrivato
  • *
  • Post: 14
  • Respect: +2
    • Mostra profilo
  • Dispositivo Android:
    HTC Tattoo
  • Play Store ID:
    Audero Team
Re:Multi Choice Dialog, premendo Cancel mi sballa i valori
« Risposta #5 il: 29 Settembre 2011, 15:25:47 CEST »
0
di nulla :D
comunque se non salvi i valori nell'array temporaneo è tutto inutile...

Codice (Java): [Seleziona]
daysMultiChoiceListener = new DialogInterface.OnMultiChoiceClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton, boolean isChecked) {
                                dWeekTmp[whichButton] = isChecked;
                                }

non fa tutto solo                ->                 // va a modificare automaticamente dWeekTmp

per lui è un array di input... il metodo non conosce mica tu come chiami i parametri che passi  :-P

Offline funcool

  • Nuovo arrivato
  • *
  • Post: 42
  • Respect: +3
    • Mostra profilo
  • Dispositivo Android:
    Acer Liquid CM 7.1
  • Play Store ID:
    elcasa
  • Sistema operativo:
    Windows 8
Re:Multi Choice Dialog, premendo Cancel mi sballa i valori
« Risposta #6 il: 01 Ottobre 2011, 10:53:10 CEST »
0
guarda.. così com'è funziona, con dWeekTmp[whichButton] = isChecked; commentato
per non saper ne leggere ne scrivere l'avevo già provata con 2 textView contenenti Tmp e Valid e , e anche con dWeekTmp[whichButton] = isChecked; commentato il tmp veniva modificato.. copia valori corretti nel Valid ecc