1

I've been struggling with this for more than two weeks. been on all the SO questions about sharedpreferenes and other 'hacks' to persist a multiple choice alertdialog. but unfortunately i still can't make it work.

Can someone please explain to me how to make this thing work ? my multiple choice alertdialog works. but i still can't save the selected items..

My code :

    public class TimelineSettings extends DialogFragment {
    Context context;
    final ArrayList selected_categories = new ArrayList();
    final String[]items = {"Fourniture","Nourriture","Voyages","Habillement","Médias","Autres"};
    TinyDB tinydb = new TinyDB(context);
    private SharedPreferences sharedPreference;
    private SharedPreferences.Editor sharedPrefEditor;

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        // Set the dialog title
        builder.setTitle("Choisissez vos paramètres")
                .setMultiChoiceItems(items, null,
                        new DialogInterface.OnMultiChoiceClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int indexselected,
                                                boolean isChecked) {
                                if (isChecked) {
                                    // If the user checked the item, add it to the selected items
                                    selected_categories.add(indexselected);
                                } else if (selected_categories.contains(indexselected)) {
                                    // Else, if the item is already in the array, remove it
                                    selected_categories.remove(Integer.valueOf(indexselected));
                                }
                            }
                        })
                        // Set the action buttons
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                    tinydb.putList("selected",selected_categories);
                    }
                })
                .setNegativeButton("Annuler", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                    }
                });
        return builder.create();
    }
}

Thanks for your help.

PS : I came across this answer, if you can explain to me how to make this work, it would be great.

Community
  • 1
  • 1
RidRoid
  • 961
  • 3
  • 16
  • 39
  • When you launch the dialog a second time, your choices are not set, is that it? – joao2fast4u Oct 21 '14 at 09:40
  • You are not saving anything to shared preferences to begin with. Nor are you retrieving anything from shared preferences when you build up the dialog. Nor are you setting choices selected at build. So what have you tried so far? You are not retrieving info from the db either. Nor saving the state of the db. – greenapps Oct 21 '14 at 09:52
  • @greenapps I tried first to store my arraylist on sharedprefs, to do so i tried to convert my arraylist to a set of strings..but that did not work..I then tried to use this tinydb class, but again i could not make it work..my problem is that i don't know exactly how to use the sharedprefs to store and then retrieve my array of selected choices. can you please show me how ? – RidRoid Oct 21 '14 at 19:23
  • @joao2fast4u yes exactly :) – RidRoid Oct 21 '14 at 19:24
  • Are you having any crash when you click ok button? – joao2fast4u Oct 22 '14 at 00:14
  • Please show the code you tried to put the selected items in shared preferences. That very well is doable using a StringSet. – greenapps Oct 22 '14 at 08:18
  • mContext is empty please try to initialize it – Sainath Patwary karnate Oct 28 '14 at 11:31

1 Answers1

3

Be careful because you are saving Integers in preferences and then you are converting an ArrayList of Integers to an ArrayList of Strings. This may cause an Exception. Use ArrayLists of Strings everywhere instead.

You are only missing the part where, before you show your DialogFragment, you have to read your saved choices and check them in your DialogFragment.

There are easiest ways of doing what you want but let's take this approach:

As you have noticed, the setMultiChoiceItems() method receives a String[] as the items of your DialogFragment and a boolean [] to define if they are checked or not. We are going to use this array to persist our choices. This array must have the same length as the items array and will be initially set to false.

On the first time you launch the DialogFragment, no items are checked. On the second time, when you already have items checked, you are going to read those choices from TinyDB and populate the boolean array with a for statement. Then you feed it to the DialogFragment builder.

The items that were saved will appear as checked on the DialogFragment, as you wished to do.

Here is the complete changed and working code:

    public class TimelineSettings extends DialogFragment {
    ArrayList<String> selected_categories = new ArrayList<String>();
    final String[]items = {"Fourniture","Nourriture","Voyages","Habillement","Médias","Autres"};
    boolean[] itemsChecked = {false, false, false, false, false, false};
    TinyDB tinydb;
    private SharedPreferences sharedPreference;
    private SharedPreferences.Editor sharedPrefEditor;

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        tinydb = new TinyDB(getActivity());
        selected_categories = tinydb.getList("selected");

        for(int i=0;i<itemsChecked.length;i++){
            if(selected_categories.contains((String)String.valueOf(i)))
                    itemsChecked[i]=true;
        }

        // Set the dialog title
        builder.setTitle("Choisissez vos paramètres")
                .setMultiChoiceItems(items, itemsChecked,
                        new DialogInterface.OnMultiChoiceClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int indexselected,
                                                boolean isChecked) {
                                if (isChecked) {
                                    // If the user checked the item, add it to the selected items
                                    if(!selected_categories.contains((String)String.valueOf(indexselected))){
                                        selected_categories.add(String.valueOf(indexselected));
                                        itemsChecked[indexselected]=true;
                                    }
                                } else if (selected_categories.contains((String)String.valueOf(indexselected))) {
                                    // Else, if the item is already in the array, remove it
                                    selected_categories.remove((String)String.valueOf(indexselected));
                                    itemsChecked[indexselected]=false;
                                }
                            }
                        })
                        // Set the action buttons
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        tinydb.putList("selected",selected_categories);
                    }
                })
                .setNegativeButton("Annuler", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                    }
                });
        return builder.create();
    }
}
Jason Aller
  • 3,541
  • 28
  • 38
  • 38
joao2fast4u
  • 6,868
  • 5
  • 28
  • 42
  • thanks for your reply, I indeed had some errors about types (when trying to convert my array to a set..). Now i'm trying to use your core but i get a nullpointer exception when I create the tinydb object : **TinyDB tinydb = new TinyDB(context);** ' What Did i go wrong ? here is the my class with the error on the comment: https://gist.github.com/RidouaneHicham/f7e07445a76a314d7c0b – RidRoid Oct 27 '14 at 11:23
  • Your context variable is empty, hence the NPE you are receiving. You have to provide a valid context to the TinyDB constructor. Try with TinyDB tinydb = new TinyDB(getActivity()); – joao2fast4u Oct 27 '14 at 12:35
  • I tried it before posting my comment..still a NPE :( – RidRoid Oct 28 '14 at 11:08
  • Could you please post your StackTrace? – joao2fast4u Oct 28 '14 at 11:14
  • yess !thank you! the NPE is gone. for a second I had that idea of moving that line inside the function...but what is the logic behind that ? what was wrong with the first declaration ? – RidRoid Oct 28 '14 at 11:30
  • 1
    @RidouaneHicham Obviously, for having a not null `Activity` context you have to extract it only when the dialog is created. If you do it before, it is null and the call will return null. – joao2fast4u Oct 28 '14 at 11:33
  • I'm back with another problem with the same class. i failed to pass the selected items (the arraylist) to the host activity. can help me please ? @joao2fast4u [here is the question](http://stackoverflow.com/questions/26992215) – RidRoid Nov 18 '14 at 13:35