定时非模态对话框

12

有没有一种方法可以显示一个非模态对话框——允许用户与对话框进行交互,在对话框弹出之前用户可以与屏幕上的其他内容进行交互?

我知道有Toast,但它们不允许与弹出窗口进行交互。

我知道对话框,但它们是模态的,不允许与背景进行交互。

我知道通知,但我想要一些在屏幕上可见的东西。

基本上,我想要能够在玩游戏或做其他事情时出现弹出窗口,告诉我收到了新邮件之类的消息。我可以单击它查看电子邮件,但如果我只想继续玩游戏,我也可以等待它消失。这在Android中是否可能?


你希望通知只出现在你的活动中,还是可能会出现在其他活动中? - Jean Hominal
3个回答

14

是的,创建一个样式为Theme.Dialog的Activity。这是一个正常的活动,看起来像对话框,同时是无模态的并接受事件。

以下是一个示例:

<activity android:name=".activity.dialog.PhotoDialog"
          android:label="@string/photo_dialog_title"
          android:theme="@android:style/Theme.Dialog"/>

编辑:

确实,Theme.Dialog会使底层的活动模糊不清,并且无法访问。我曾在这里有一个类似的需求,需要显示带有文本和取消按钮的上传进度对话框。主要的问题是设置WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL并重置WindowManager.LayoutParams.FLAG_DIM_BEHIND

创建自定义内容的对话框:

    if (progressDialog == null) {
            progressDialog = new Dialog(activityRequestingProgressDialog);
            progressDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            progressDialog.setContentView(R.layout.progress_upload);
            progressBar = (ProgressBar) progressDialog.findViewById(R.id.progressBar);
            progressText = (TextView) progressDialog.findViewById(R.id.progressText);
            progressText.setText("0 %");
            progressText.setTextSize(18);
            Button buttonCancel = (Button) progressDialog.findViewById(R.id.btnCancel);
            buttonCancel.setOnClickListener(new View.OnClickListener() {
                public void onClick(View view) {
                    cancelProgressDialog();
                    stopUpload("Upload cancelled.");
                }
            });
            Window window = progressDialog.getWindow();
            window.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
            window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
            window.setGravity(Gravity.BOTTOM);
            progressDialog.show();
        }

        progressText.setText(text);
        progressBar.setProgress(percent);

这是此对话框的布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@+id/progressDialog"
          android:orientation="vertical"
          android:layout_height="wrap_content"
          android:layout_width="wrap_content"
          android:layout_centerVertical="true">

<TextView android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_gravity="center"
          android:textSize="18sp"
          android:padding="10dp"
          android:text="@string/progress_title"/>

<LinearLayout android:id="@+id/progressDialog"
              android:orientation="horizontal"
              android:layout_height="wrap_content"
              android:layout_width="wrap_content"
              android:padding="10dp"
              android:layout_centerVertical="true">

    <ProgressBar android:id="@+id/progressBar"
                 android:layout_width="150dp"
                 android:layout_height="34dp"
                 android:paddingRight="10dp"
                 android:max="100"
                 android:progress="0"
                 android:fadingEdge="vertical"
                 style="?android:attr/progressBarStyleHorizontal"/>

    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_gravity="center"
              android:id="@+id/progressText"
              android:paddingRight="10dp"/>

    <Button android:layout_height="40dp"
            android:layout_width="80dp"
            android:id="@+id/btnCancel"
            android:text="@string/dialog_cancel"/>

</LinearLayout>
</LinearLayout>

这仍然允许与其背后的活动交互吗? - Grantland Chew
所以我进行了测试以确保它能够像我想的那样模糊掉其后面的活动... - Grantland Chew
1
你说得对。我把它和其他解决方案混淆了。我现在发布了正确的代码。 - Peter Knego
这个方法的签名是 window.setFlags(flag, mask)。 使用 (flag, flag) 调用它可以确保其他标记不会改变。 实际上最好使用 addFlag(flag),因为它以较少的歧义执行相同的操作。 - Peter Knego
你好,我该如何自定义警告框的布局? - newton_guima
显示剩余2条评论

4

只需在您的对话框中添加FLAG_NOT_TOUCH_MODAL标志即可。

dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);  

0

我的实现方式可能有些临时抱佛脚,但也可以让后台窗口捕捉到按钮按下的事件。

_wm = this.getWindowManager();
LayoutInflater layoutInflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
_view = layoutInflater.inflate(R.layout.notification, null);

_params = new WindowManager.LayoutParams();
_params.height = android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
_params.width = android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
_params.flags = 
    // this is to keep button presses going to the background window
    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
    // this is to enable the notification to recieve touch events
    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
// background transparant
_params.format = PixelFormat.TRANSLUCENT;
_gravity = Gravity.TOP;//Gravity.BOTTOM;

_wm.addView(_view, _params);

在许多情况下工作良好...但是我在对话框后面有一个ListView,而我无法选择任何ListView元素...请问如何使ListView元素可点击? - fvisticot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接