I saw much people wanted such a feature, me either. These days I've google-ed around and tried several ways to get it right, finally ended up with following solution. No thread synchronization, no dialog- themed activities, really simple and straight.
Some useful resource and background, http://groups.google.com/group/android-developers/browse_thread/thread/5616a220c97a13fc/5e722e601f33d884#5e722e601f33d884 http://stackoverflow.com/questions/2028697/dialogs-alertdialogs-how-to-block-execution-while-dialog-is-up-net-style Modal dialog is a typical widget in Win32, it could 1. block current workflow 2. capture all input (key, mouse) events, but still properly dispatch other events, like paint 3. wait for response and quit People who's familiar with Win32 programming possibly knows how to implement a modal dialog. Generally it runs a nested message loop (by GetMessage/PostMessage) when there is a modal dialog up. So, I tried to implement my own modal dialog in this traditional way. At the first, android didn't provide interfaces to inject into ui thread message loop, or I didn't find one. When I looked into source, Looper.loop(), I found it's exactly what I wanted. But still, MessageQueue/Message haven't provided public interfaces. Fortunately, we have reflection in java. Basically, I just copied exactly what Looper.loop() did, it blocked workflow and still properly handled events. I haven't tested nested modal dialog, but theoretically it would work. Here's my source code, public class ModalDialog { private boolean mChoice = false; private boolean mQuitModal = false; private Method mMsgQueueNextMethod = null; private Field mMsgTargetFiled = null; public ModalDialog() { } public void showAlertDialog(Context context, String info) { if (!prepareModal()) { return; } // build alert dialog AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(info); builder.setCancelable(false); builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { ModalDialog.this.mQuitModal = true; dialog.dismiss(); } }); AlertDialog alert = builder.create(); alert.show(); // run in modal mode doModal(); } public boolean showConfirmDialog(Context context, String info) { if (!prepareModal()) { return false; } // reset choice mChoice = false; AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(info); builder.setCancelable(false); builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { ModalDialog.this.mQuitModal = true; ModalDialog.this.mChoice = true; dialog.dismiss(); } }); builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { ModalDialog.this.mQuitModal = true; ModalDialog.this.mChoice = false; dialog.cancel(); } }); AlertDialog alert = builder.create(); alert.show(); doModal(); return mChoice; } private boolean prepareModal() { Class<?> clsMsgQueue = null; Class<?> clsMessage = null; try { clsMsgQueue = Class.forName("android.os.MessageQueue"); } catch (ClassNotFoundException e) { e.printStackTrace(); return false; } try { clsMessage = Class.forName("android.os.Message"); } catch (ClassNotFoundException e) { e.printStackTrace(); return false; } try { mMsgQueueNextMethod = clsMsgQueue.getDeclaredMethod("next", new Class[]{}); } catch (SecurityException e) { e.printStackTrace(); return false; } catch (NoSuchMethodException e) { e.printStackTrace(); return false; } mMsgQueueNextMethod.setAccessible(true); try { mMsgTargetFiled = clsMessage.getDeclaredField("target"); } catch (SecurityException e) { e.printStackTrace(); return false; } catch (NoSuchFieldException e) { e.printStackTrace(); return false; } mMsgTargetFiled.setAccessible(true); return true; } private void doModal() { mQuitModal = false; // get message queue associated with main UI thread MessageQueue queue = Looper.myQueue(); while (!mQuitModal) { // call queue.next(), might block Message msg = null; try { msg = (Message)mMsgQueueNextMethod.invoke(queue, new Object[]{}); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } if (null != msg) { Handler target = null; try { target = (Handler)mMsgTargetFiled.get(msg); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } if (target == null) { // No target is a magic identifier for the quit message. mQuitModal = true; } target.dispatchMessage(msg); msg.recycle(); } } } } Hopefully this would help. -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en