Force user to select option in dialog
android, android-dialog, android-dialogfragment, android-fragments
Solution
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`.
Problem
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(); } } ``` }