这几天在做自定义布局的dialog时,踩了不少的坑,现在记录下自认为最大的坑。
首先,我们来创建一个定义dialog布局的xml文件。
dlg_test.xml:
在这个布局文件中,我只放了两个控件,一个TextView和一个Button,宽度都为wrap_content,最外层是一个宽度为match_parent的LinearLayout。
然后在main_activity中放置一个按钮,便于弹出该dialog。以下为MainActivity中弹出dialog的代码:
open_dlg.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlertDialog dlg = new AlertDialog.Builder(MainActivity.this, R.style.testDlg).create();
dlg.show();
dlg.setContentView(R.layout.dlg_test);
}
});
dialog的样式是我在style文件中定义的,只需要在style文件中加入下面这行代码即可:
这样,一个简单的自定义dialog就实现了,效果如下:
可以看到,这个dialog的大小刚好为容纳所有控件的大小。
接下来我们改变一下button的宽度,改为match_parent。可想而知,此时button应该横占一行,根据android studio的可视化界面我们也可以看到确实如此:
我们猜想,dialog应该也会随之被撑大吧。但是当dialog显示出来时,我们的内心是奔溃的:
大家别以为我把第一幅图copy下来了,这真的是改变后的dialog,好像没什么变化呢,这是为什么啊?
经过我的不断折腾之后,我终于弄懂了是为什么。
这是因为在dialog中,我们的最外层布局,即上面的LinearLayout的宽度和高度都变成了wrap_content。为了证明这一点,我们把dlg_test.xml中的LinearLayout的宽度高度都改为wrap_content
dlg_test.xml:
可视化界面如下:
图中虚线代表当前LinearLayout的大小,仔细看,我们会发现,这个与我们显示的dialog是一样大小的。据此可以知道,dialog最外层的布局宽度和高度确实被设定为wrap_content。
当最外层布局宽度为wrap_content时,其宽度值是:所有layout_width为wrap_content的直接子控件的宽度的最大值(这里的直接子控件指的是第二层布局或者控件),这样的话,大于该最大值的控件就会出现一个问题——宽度只能全部变为这个最大值,所以我们的button即使设置了match_parent,也无法将dialog撑开。而且,如果我们某些控件所显示的文本太多时,这个最大值宽度并不一定能容纳这些文本,此时就会出现文本换行甚至是不可见的情况。
为了能更好的理解这一点,下面再来修改一下dlg_test.xml:
这里我增加了一个第二层布局LinearLayout,宽度高度都为match_parent,其中还包含了一个文本为222的TextView,并且TextView的宽度高度
都为wrap_content。
另外我还加了一个第二层控件TextView,文本为1,宽度高度都为wrap_content。
接下来我们看一下可视化界面的效果以及dialog的真实效果:
可以看到,这两个的效果是一模一样的,而且dialog的宽度只刚好包含了文本为1的TextView,而不能刚好包含其他控件,所以可知dialog宽度的取值规律确实为:所有layout_width为wrap_content的直接子控件的宽度的最大值(这里的直接子控件指的是第二层布局或者控件)。
那么,为了保证我们想展示的内容不变形,我们在书写dialog的布局文件时,最外层一开始就都用wrap_content的宽度,这样就能在可视化界面中看到真正的dialog模样,同时第二层布局或者控件要统一宽度,要么都为wrap_content,要么都为match_parent,这样才能确保控件大小的正常。