当前位置: 首页 > 知识库问答 >
问题:

在AlertDialog后面设置窗口背景会删除对话框居中

谷飞星
2023-03-14

我正在创建一个AlertDialog与自定义视图和窗口背景。设置一个ColorDrawable如预期的那样工作,但是从资源中设置一个BitmapDrawable会使对话框出现在屏幕的正上方(而不是居中)。(注意:我说的是对话框背后的背景(通常是透明的灰色,而不是对话框的背景本身!)

对话框背景(@drawable/Dialog_bg):

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/white" />
    <corners android:radius="10dp" />
</shape>

对话框布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/dialog_bg"
    android:orientation="vertical">

    <!-- dialog contents -->

</LinearLayout>

用于显示可着色的对话框的代码:-

private void showDialog() {
    final AlertDialog dialog;
    @SuppressLint("InflateParams") final ViewGroup dialogView = (ViewGroup) activity.getLayoutInflater().inflate(R.layout.my_dialog, null);
    dialog = new AlertDialog.Builder(activity).setView(dialogView).create();
    // this works:
    dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    dialog.show();
}

代码显示与BitmapDrawable从资源(加载一个简单的PNG)的对话框:-

private void showDialog() {
    final AlertDialog dialog;
    @SuppressLint("InflateParams") final ViewGroup dialogView = (ViewGroup) activity.getLayoutInflater().inflate(R.layout.my_dialog, null);
    dialog = new AlertDialog.Builder(activity).setView(dialogView).create();
    // this sets the background, but un-centers the dialog:
    BitmapDrawable drawable = (BitmapDrawable) ResourcesCompat.getDrawable(activity.getResources(), R.drawable.my_bg, null);
    dialog.getWindow().setBackgroundDrawable(drawable);
    dialog.show();
}

如预期的那样设置可绘制的颜色:对话框后面的背景是彩色的,对话框仍然以屏幕为中心。设置BitmapDrawable不起作用:设置了背景,但对话框移动到屏幕顶部。

同样不起作用的事情:

  • 加载绘图与ContextCompat.getDrawable()(这是相同的ResourcesCompat.getDrawable()与当前主题而不是空)
  • 使用DisplayMetrics和dialog.getWindow(). getAtinites(). y(分别为. x)自己计算边距:(高度-y)/2-

那么,有人知道如何在对话框后面设置PNG背景并使其在屏幕上居中吗?

共有2个答案

高建本
2023-03-14

所以我就解决了这个问题,尽管我不得不承认这有点骇人。

首先,我禁用了对话框后面的淡入淡出

dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

并通过添加视图手动“淡入”活动,将活动覆盖在半透明的黑色上:

final ViewGroup dimBackgroundView = new FrameLayout(activity);
float dimAlpha = 0.5f;
dimBackgroundView.setBackgroundColor(Color.BLACK);
dimBackgroundView.setAlpha(dimAlpha);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
activityLayout.addView(dimBackgroundView, params);

这还需要我手动变暗支持设备(SDK 21)上的状态栏:

final int statusBarColor;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
    statusBarColor = activity.getWindow().getStatusBarColor();
    activity.getWindow().setStatusBarColor(
            Color.rgb((int) (Color.red(statusBarColor) + 255 * dimAlpha),
                    (int) (Color.green(statusBarColor) + 255 * dimAlpha),
                    (int) (Color.blue(statusBarColor) + 255 * dimAlpha)));
} else {
    statusBarColor = Color.BLACK;
}

之后,我将预期的背景添加到活动中(dialogBgView位于半透明的黑色视图之上),并继续正常添加对话框。由于我现在已将所有这些视图添加到活动中,因此需要在对话框中删除它们:

dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
    @Override
    public void onDismiss(DialogInterface dialogInterface) {
        // remove dim
        activityLayout.removeView(dimBackgroundView);
        // restore original statusbar color
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().setStatusBarColor(statusBarColor);
        }
        // remove background image
        activityLayout.removeView(dialogBgView);
    }
});

这很有效,但这真的不是一个好的解决方案。所以如果有人发现了更好的方法,请随时在这里发布。

隗翰海
2023-03-14

我们使用WindowManger for Dialog指定自定义窗口属性:

这里给出的布局参数通常应该来自以前使用{@link#getAttributes()}检索的值;您可能不想盲目地创建和应用您自己的,因为这将吹走您不感兴趣的框架设置的任何值。

只需根据您的要求添加以下属性:

 /**
 * Retrieve the current window attributes associated with this panel.
 *
 * @return WindowManager.LayoutParams Either the existing window
 *         attributes object, or a freshly created one if there is none.
 */

 WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
    params.gravity = Gravity.TOP;

 /**
 * Set the width and height layout parameters of the window.  The default
 * for both of these is MATCH_PARENT; you can change them to WRAP_CONTENT
 * or an absolute value to make a window that is not full-screen.
 *
 * @param width The desired layout width of the window.
 * @param height The desired layout height of the window.
 *
 * @see ViewGroup.LayoutParams#height
 * @see ViewGroup.LayoutParams#width
 */
    dialog.getWindow().setLayout((int) (getScreenWidth(activity)), ViewGroup.LayoutParams.MATCH_PARENT);
    dialog.getWindow().setBackgroundDrawableResource(R.drawable.message_email_selected);
 /**
 * Specify custom window attributes.  <strong>PLEASE NOTE:</strong> the
 * layout params you give here should generally be from values previously
 * retrieved with {@link #getAttributes()}; you probably do not want to
 * blindly create and apply your own, since this will blow away any values
 * set by the framework that you are not interested in.
 *
 * @param a The new window attributes, which will completely override any
 *          current values.
 */
    dialog.getWindow().setAttributes(params);

例如:

 final Dialog dialog = new Dialog(getActivity());
            WindowManager.LayoutParams params = dialog.getWindow().getAttributes();
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setContentView(R.layout.dialog_view);
            //            dialog.getWindow().setBackgroundDrawable(null);
            dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
            dialog.getWindow().setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            dialog.getWindow().setAttributes(params);
            dialog.show();
//Access dialog views
 TextView txt_cancel = (TextView) dialog.findViewById(R.id.txt_cancel);
 类似资料:
  • 我希望对话框下有模糊的屏幕,所以我拍摄活动的“截图”,模糊它,并将其设置为可位图绘制的对话框窗口背景。奇怪的是对话框不再集中在屏幕上,即使调用了setCanceledOnTouchOutside(true),触摸外部对话框也不会关闭它。 问题是:为什么这不起作用?分别如何创建背景模糊的对话框?

  • 以下是我如何调用DialogFragment: 以下是(部分)我的DialogFragment是如何创建的: 这是我的DialogSelectAccount的xml 问题是始终显示一个无害的白色背景,如下所示。如何删除它?

  • 我有一个JButton,我想设置背景的颜色。 我在mac电脑上用了这个,它显示了我想要的样子。然而,在windows上试用时,前景是白色的(正如它应该的那样),但背景是空的。 将背景色设置为JButton 表示添加

  • 我想用透明的背景显示警报对话框。我的警报对话框代码为: 我的背景图像包含圆形的角,但不幸的是,流行是以矩形白色背景出现的。任何身体plz建议我的想法。提前谢谢。

  • 以下是我的AlertDialog无响应状态的屏幕截图: 在背景中,绿色瓷砖、黑色和白色目标中的红色球,所有三个位图都在一个渲染线程上连续渲染,该线程锁定/解锁手机上的背景画布。当我按下OK按钮时,无论我在EditText中输入了什么文本,都会执行此无响应操作。 这是代码: 游戏活动班: 由于未知原因,只有在AlertDialog之前存在准备好的活套时,AlertDialog才会执行。调用show(

  • 继承自Popup 对话框是一个原生对话弹出框,显示一个消息与最多三个按钮。关闭时会被自动释放。 使用“const {AlertDialog} = require('tabris');”引入该类。 属性 buttons Type: {ok?: string, cancel?: string, neutral?: string} 含有按钮文本内容的对象。分别是这三种按钮:ok, cancel和neut