8

On starting the application for the first time I wanted to prompt the user (by dialog) to select their city, which would then consequently save their preference and load the proper data into the listview. However, I've noticed that a dialog can be closed by the back button, or pushing anywhere outside of the dialog box, which then triggers a null value for the database.

Is there anyway I can force the dialog box to stay open until the user has selected an option?

I've already implemented .setCancelable(false) and this does not seem to work. My code is below, DialogSetup being the inner class that I'm working with.

Any help/ideas would be appreciated.

public class MainActivity extends ListActivity {
private Cursor lines;
private MetroSleepDb db;
private ListAdapter adapter;
public static final String PREFS_NAME = "METROSLEEP_PREFS";

@Override
protected void onCreate(Bundle savedInstanceState) {


    super.onCreate(savedInstanceState);



    chooseCityDialog();




}




public void setAdapters() {

    db = new MetroSleepDb(this);
    lines = db.getLines(); // you would not typically call this on the main thread
    //ListView listView = (ListView) findViewById(R.id.li);
    adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, 
            lines, 
            new String[] {"line_id"}, 
            new int[] {android.R.id.text1}, 0);


    getListView().setAdapter(adapter);
    getListView().setOnItemClickListener(onAnswerClicked);

}


public String getItem(int pos) {

    Cursor c = (Cursor) adapter.getItem(pos);
    String value = c.getString(c.getColumnIndex("line_id"));
    return value;
}

private OnItemClickListener onAnswerClicked = new OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position,
            long id) {

        String line_value = getItem(position);
        Intent intent = new Intent(MainActivity.this, ChooseStations.class);
        intent.putExtra("line", line_value);
        startActivity(intent);
    }

};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}


@Override
public boolean onOptionsItemSelected(MenuItem  item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        // This ID represents the Home or Up button. In the case of this
        // activity, the Up button is shown. Use NavUtils to allow users
        // to navigate up one level in the application structure. For
        // more details, see the Navigation pattern on Android Design:
        //
        // http://developer.android.com/design/patterns/navigation.html#up-vs-back
        //
        NavUtils.navigateUpFromSameTask(this);
        return true;

    case R.id.menu_settings:
        Intent intent = new Intent(this, SettingsActivity.class);
        startActivity(intent);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

public void chooseCityDialog() {
    DialogFragment newFragment = new DialogSetup();
    newFragment.show(getFragmentManager(), "citypref");
}

public static final class DialogSetup extends DialogFragment {
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle(R.string.prompt_choose_city)
               .setCancelable(false) 
               .setItems(R.array.Cities, new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int which) {
                       //
               }
        });

        return builder.create();
    }



}

}

markbratanov
  • 878
  • 3
  • 17
  • 39
  • Could you use that null value trigger as a way to start the dialog again to get an answer? – TronicZomB Apr 10 '13 at 19:02
  • I could check to see if no value was selected and re-trigger the dialog. That is indeed a solution, thanks. – markbratanov Apr 10 '13 at 19:04
  • 2
    You also could use an `onDismissListener` to not dismiss if there is no value, I believe. Althoug, I don't know why `setCancelable(false)` isn't working. I haven't used a `DialogFragment` but works fine in other `Dialogs` – codeMagic Apr 10 '13 at 19:05

3 Answers3

8

Aha! You have to call setCancelable(false) on the DialogFragment, not the AlertDialog.builder. See this question: AlertDialog's setCancelable(false) method not working.

The documentation for DialogFragment.setCancelable(boolean cancelable) states:

Control whether the shown Dialog is cancelable. Use this instead of directly calling Dialog.setCancelable(boolean), because DialogFragment needs to change its behavior based on this.

You just need to add 1 line of code:

public void chooseCityDialog() {
    DialogFragment newFragment = new DialogSetup();
    newFragment.setCancelable(false);
    newFragment.show(getFragmentManager(), "citypref");
}

Also, it would be a nice safety check to have a default city to fall back to, if somehow the city returned from the Dialog is null.

Community
  • 1
  • 1
Steven Byle
  • 13,149
  • 4
  • 45
  • 57
3

I would just use an AlertDialog instead of DialogFragment for this.

    AlertDialog dlgBuilder = new AlertDialog.Builder(this);
    dlgBuilder.setMessage("Title");
    dlgBuilder.setCancelable(false)
            .setPositiveButton("OK", new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    okCalledMethodInactivity();
                    dialogInterface.dismiss();
                }
            })
            .setNegativeButton("Exit app", new OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    finish();
                }
            });
    AlertDialog dlg = dlgBuilder.create();
    dlg.show();
500865
  • 6,920
  • 7
  • 44
  • 87
  • 1
    Disagree, Google recommends you use `DialogFragment`s - http://android-developers.blogspot.com/2012/05/using-dialogfragments.html – Steven Byle Apr 10 '13 at 19:33
  • It is a bit confusing because the AlertDialog indeed lets you use `alertDialog.setCanceledOnTouchOutside(false);` and `alertDialog.setCancelable(false);` but I cannot seem to get a ListView inside a alertDialog without using the builder, which returns: **The method setCanceledOnTouchOutside(boolean) is undefined for the type AlertDialog.Builder** – markbratanov Apr 10 '13 at 19:42
  • Probably you need to use [setMultiChoiceItems](http://developer.android.com/reference/android/app/AlertDialog.Builder.html#setMultiChoiceItems(java.lang.CharSequence[], boolean[], android.content.DialogInterface.OnMultiChoiceClickListener)). I see the method setCanceledOnTouchOutside in the DialogInterface. So you need to first build the alert dialog and then use that method. – 500865 Apr 10 '13 at 19:50
  • @markbratanov look at my answer, you need to call `setCancelable(false)` on the `DialogFragment`, since it is handling the behavior of the `AlertDialog`. – Steven Byle Apr 10 '13 at 19:56
  • @StevenByle : Check this. http://developer.android.com/guide/faq/commontasks.html#alerts . Alert dialog still does the job. DialogFragment feels like a neat solution but IMO it is a overkill for such a small task. – 500865 Apr 10 '13 at 22:21
  • @500865 `AlertDialog` is by no means dead. but by using `DialogFragment`, you get the state management of the `Dialog` provided by the `Fragment`, rather than having the track the state of your `AlertDialog` from within your parent `Activity` or `Fragment`. In reality, `DialogFragment` is just a wrapper for `AlertDialog`. I believe those docs are old, and have not been updated. By using `DialogFragment`, the OP has a more robust solution IMO, and I use them as well in all of my apps. – Steven Byle Apr 10 '13 at 22:31
  • I agree that `DialogFragment` has its own benefits and regular Dialog Widgets (AlertDialog, ProgressDialog etc.,) its own. I don't think google would recommend using DialogFragment for every little dialogs you create. The choice depends on the problem you are trying to solve using the dialog box. – 500865 Apr 10 '13 at 23:07
-4

Disable the back button by

@Override
public void onBackPressed() {

}
Parijat Bose
  • 380
  • 1
  • 6
  • 22