Could somebody please ban this idiot already? On Jun 1, 9:47 pm, Qi <qilu...@gmail.com> wrote: > 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/threa...http://stackoverflow.com/questions/2028697/dialogs-alertdialogs-how-t... > > 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