Why do you keep advertisiting this horrible hack????
On Jun 2, 8:51 pm, Qi Luo <[email protected]> wrote: > I saw much people wanted such a feature, me either. These days I've > google-ed around and tried serveral ways to get it right, finally > ended up with following solution. No thread synchronization, no > dialog-themed activities, really simple. > 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 [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/android-developers?hl=en

