代码之家  ›  专栏  ›  技术社区  ›  Cheok Yan Cheng

如何将对话框窗口背景设置为透明,而不影响其边距

  •  15
  • Cheok Yan Cheng  · 技术社区  · 10 年前

    目前,我有以下对话框,我将对其项执行展开/折叠动画。

    enter image description here

    此对话框通过以下代码创建

    import android.support.v7.app.AlertDialog;
    
    final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    final AlertDialog dialog = builder.setView(view).create();
    final ViewTreeObserver vto = view.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    
        public void onGlobalLayout() {
            ViewTreeObserver obs = view.getViewTreeObserver();
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                obs.removeOnGlobalLayoutListener(this);
            } else {
                obs.removeGlobalOnLayoutListener(this);
            }
    
            // http://stackoverflow.com/questions/19326142/why-listview-expand-collapse-animation-appears-much-slower-in-dialogfragment-tha
            int width = dialog.getWindow().getDecorView().getWidth();
            int height = dialog.getWindow().getDecorView().getHeight();
            dialog.getWindow().setLayout(width, height);
        }
    });
    

    但是,当执行动画时,会有副作用。

    enter image description here

    请注意,动画后对话框中不需要的额外白色区域不是由我们的自定义视图造成的。它是对话框本身的系统窗口白色背景。

    我倾向于使对话框的系统窗口背景变得透明。

    final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
    final AlertDialog dialog = builder.setView(view).create();
    dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
    

    虽然不再看到不需要的白色背景,但对话框的原始边距也消失了。(对话框宽度现在为全屏宽度)

    enter image description here

    我怎样才能使它透明,而不影响它的边距?

    6 回复  |  直到 10 年前
        1
  •  15
  •   Bartek Lipinski    6 年前

    有一个非常简单的方法可以做到这一点:

    您需要“修改” Drawable 被用作 Dialog .那种 Dialogs 使用 InsetDrawable 作为背景。

    API>=23

    只有SDK API 23+允许您获取源代码 可绘制的 可插入绘制 ( getDrawable() 方法)。有了这个,你可以做任何你想做的事——例如,把颜色换成完全不同的东西(比如 RED 或其他)。如果使用此方法,请记住 可绘制的 是一个 GradientDrawable 而不是 ColorDrawable !

    API<23

    对于较低的API,您的(“优雅”)选项非常有限。

    幸运的是,您不需要将颜色更改为某个疯狂值,只需将其更改为 TRANSPARENT 。为此,您可以使用 setAlpha(...) 方法 可插入绘制 .

    InsetDrawable background = 
                (InsetDrawable) dialog.getWindow().getDecorView().getBackground();
    background.setAlpha(0);
    

    编辑 (由于 Cheok Yan Cheng's 评论) :

    或者你可以跳过选角 可插入绘制 并得到相同的结果。请记住,这样做会导致 alpha 将在 可插入绘制 而不是在 可绘制的 可插入绘制 .


    retaining spacings

        2
  •  2
  •   pRaNaY    10 年前

    尝试在主题下面:

    <style name="TransaparantDialog">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:windowFrame">@null</item>
        <item name="android:windowTitleStyle">@null</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
        <item name="android:windowContentOverlay">@null</item>
        <item name="android:backgroundDimEnabled">false</item>
        <item name="android:background">@android:color/transparent</item>
        <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
    </style>
    

    尝试以下代码以应用主题 AlertDialog.Builder :

    final AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(activity, R.style.TransaparantDialog));
    ...
    dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
    

    我希望能帮助你!

        3
  •  0
  •   rekire    10 年前

    背景图像 abc_popup_background_mtrl_mult 它是compat库的一部分,在图片信息中已经包含了一个边距。

    abc_popup_background_mtrl_mult

    这就是为什么删除背景图像时,边距会消失。我强烈建议不要使用 ViewTreeObserver ,它将被多次调用,可能会导致性能问题。更好地使用屏幕大小:

    Display display = getWindowManager().getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    int width = size.x;
    int height = size.y;
    

    您的问题在布局中正确。请尝试使用层次结构查看器检查视图。

        4
  •  0
  •   Chathura Jayanath    10 年前

    只需在show对话框之后添加这一行。我更喜欢使用 Dialog 代替使用 AlertDialog

    dialog.getWindow().setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    
        5
  •  0
  •   Vilen    10 年前

    让我们从谷歌的建议开始,建议使用DialogFragment而不是简单的Dialog。

    @rekire是正确的,边距由drawable设置,接下来它由9个补丁设置,或者根据主题通过编程设置。

    因此,您可以将填充设置为内容视图,也可以使用DialogFragment创建对话框。这里是一个根据对话框内容更改对话框高度的示例,请注意,您不需要使用树观察器,这可能会导致性能问题。

    所以 实例

    dialog_confirm.xml

    <?xml version="1.0" encoding="utf-8"?>
    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="20dp">
    
        <LinearLayout android:id="@+id/container"
                      xmlns:android="http://schemas.android.com/apk/res/android"
                      android:layout_width="match_parent"
                      android:layout_height="wrap_content"
                      android:background="@android:color/white"
                      android:orientation="vertical"
                      android:animateLayoutChanges="true"
                      android:padding="15dp">
    
            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:padding="10dp"
                android:text="A label text"
                android:textAppearance="?android:attr/textAppearanceLarge"/>
    
            <TextView
                android:id="@+id/textView2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:padding="10dp"
                android:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque mauris mi, dictum a lectus ut, facilisis"
                android:textAppearance="?android:attr/textAppearanceMedium"/>
    
            <Button
                android:id="@+id/button1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="Remove Me"/>
    
            <Button
                android:id="@+id/button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="Remove Me"/>
    
            <Button
                android:id="@+id/button3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="Remove Me"/>
    
            <!-- as much content as you need -->
    
        </LinearLayout>
    </ScrollView>
    

    注意:我将所有内容都打包到滚动视图中,并设置填充,如果您愿意,可以跳过它。

    ConfirmDialog.java

    //here goes package name and  imports
    
    /**
     * Created by Vilen - virtoos.com;
     * fragment dialog example
     */
    public class ConfirmDialog extends DialogFragment implements View.OnClickListener {
    
        private Button button1;
        private Button button2;
        private Button button3;
        private LinearLayout containerLayout;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setStyle(DialogFragment.STYLE_NO_TITLE, 0);
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.dialog_confirm, container, false);
            containerLayout = (LinearLayout)v.findViewById(R.id.container);
            button1 = (Button)v.findViewById(R.id.button1);
            button2 = (Button)v.findViewById(R.id.button2);
            button3 = (Button)v.findViewById(R.id.button3);
            button1.setOnClickListener(this);
            button2.setOnClickListener(this);
            button3.setOnClickListener(this);
            return v;
        }
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            // make background transparent if you want
            //getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        }
    
        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
    
            return super.onCreateDialog(savedInstanceState);
    
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.button1:
                    containerLayout.removeView(button1);
                    break;
                case R.id.button2:
                    containerLayout.removeView(button2);
                    break;
                case R.id.button3:
                    containerLayout.removeView(button3);
                    break;
            }
        }
    }
    

    最后,您可以用这段代码显示对话框

    ConfirmDialog confirmDialog = new ConfirmDialog();
    confirmDialog.show(getSupportFragmentManager(), "dialog");
    

    enter image description here

    我不会详细解释为什么Fragment对话框更好,但有一点很清楚,您可以为它封装逻辑并拥有单独的类。 希望这能解决你的问题。

        6
  •  0
  •   Mr Lister hawi    10 年前

    应该有的是你没有展示的东西,我不确定这是你不知道的东西,或者它已经存在,所以你认为没有必要展示。

    将主题设置为Dialog,这将整个活动作为一个Dialog。我不认为你做到了,否则AlertDialog就不会出现了。

    我有点不明白你的描述,但有一点 <shape/> XML比9补丁强大得多,并且使用RelativeLayout会有所帮助。