Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: How to get a modal dialog or similar modal behavior?

These days I'm working on simulating modal dialog in Android. I've googled a lot, there's much discussions but sadly there's not much options to get it modal. Here's some background,
Dialogs, Modal Dialogs and Blockin
Dialogs / AlertDialogs: How to "block execution" while dialog is up (.NET-style)

There's no straight way to get modal behavior, then I came up with 3 possible solutions,
1. Use a dialog-themed activity, like this thread said, but I still can't make main activity truly wait for dialog-activity return. Main activity turned to stop status and got restarted then.
2. Build one worker thread, and use thread synchronization. However, it's a huge refactoring job for my app, now I have a single main activity and a service both in main UI thread.
3. Take over event handling within a loop when there is a modal dialog up, and quit loop when dialog gets closed. Actually it's the way to build a real modal dialog like what it exactly does in Windows. I still haven't prototyped this way.

I'd still like to simulate it with a dialog-themed activity,
1. start dialog-activity by startActivityForResult()
2. get result from onActivityResult()
Here's some source

public class MainActivity extends Activity {  @Override public void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);      MyView v = new MyView(this);     setContentView(v); }  private final int RESULT_CODE_ALERT = 1; private boolean mAlertResult = false; public boolean startAlertDialog() {     Intent it = new Intent(this, DialogActivity.class);     it.putExtra("AlertInfo", "This is an alert");     startActivityForResult(it, RESULT_CODE_ALERT);      // I want to wait right here     return mAlertResult; }  @Override protected void onActivityResult (int requestCode, int resultCode, Intent data) {     switch (requestCode) {     case RESULT_CODE_ALERT:         Bundle ret = data.getExtras();         mAlertResult = ret.getBoolean("AlertResult");         break;     } } } 

The caller of startAlertDialog will block execution and expect returned result. But startAlertDialog returned immediately of course, and main activity went into STOP status while DialogActivity was up.

So the question is, how to make main activity really wait for result?
Thanks.

like image 588
fifth Avatar asked May 25 '11 06:05

fifth


2 Answers

I got a modal Dialog while using:

setCancelable(false); 

on the DialogFragment (not on the DialogBuilder).

like image 80
meises Avatar answered Oct 14 '22 10:10

meises


It is not possible the way you planned. First, you are not allowed to block the UI thread. Your application will be terminated. Second, need to handle the lifecycle methods that are called when another activity is started with startActivity (your original acitvity will be paused while the other activity is running). Third, you probably could somehow hack it by using startAlertDialog() not from the UI thread, with thread synchronization (like Object.wait()) and some AlertDialog. However, I strongly encourage you to not do this. It is ugly, will certainly break and it's just not the way things are intended to work.

Redesign your approach to capture the asynchronous nature of these events. If you want for example some dialog which asks the user for a decsision (like accepting the ToS or not) and do special actions based on that decision create a dialog like this:

AlertDialog dialog = new AlertDialog.Builder(context).setMessage(R.string.someText)                 .setPositiveButton(android.R.string.ok, new OnClickListener() {                      @Override                     public void onClick(DialogInterface dialog, int which) {                         dialog.dismiss();                         // Do stuff if user accepts                     }                 }).setNegativeButton(android.R.string.cancel, new OnClickListener() {                      @Override                     public void onClick(DialogInterface dialog, int which) {                         dialog.dismiss();                         // Do stuff when user neglects.                     }                 }).setOnCancelListener(new OnCancelListener() {                      @Override                     public void onCancel(DialogInterface dialog) {                         dialog.dismiss();                         // Do stuff when cancelled                     }                 }).create(); dialog.show(); 

Then have two methods handling positive or negative feedback accordingly (i.e. proceeding with some operation or finishing the activity or whatever makes sense).

like image 42
Stephan Avatar answered Oct 14 '22 08:10

Stephan