我有一个可行的解决方案,说实话,我认为挖掘得太深,无法获得如此简单的结果。但这里是:
究竟发生了什么:
By opening the Dialog
layout with the Hierarchy Viewer, I was able to examine the entire layout of the AlertDialog
and what exactly what was going on:
![enter image description here](https://i.stack.imgur.com/AqyqJ.png)
The blue亮点是所有高级部分(Window
,框架为Dialog
视觉风格等)以及从结尾开始blue下面是组件的位置AlertDialog
are (red= 标题,yellow= 一个滚动视图存根,可能用于列表AlertDialog
s, green = Dialog
内容即自定义视图,orange= 按钮)。
从这里可以清楚地看出,7 视图路径(从blue到最后green)是什么未能正确WRAP_CONTENT
。看着LayoutParams.width
每个View
透露一切都已给予LayoutParams.width = MATCH_PARENT
并且在某个地方(我猜是在顶部)设置了尺寸。所以如果你遵循那棵树,很明显你的习惯View
在树的底部,将never能够影响的大小Dialog
.
那么现有的解决方案做了什么?
- 两者都编码方法我的问题中提到的只是获得顶部
View
并修改其LayoutParams
。显然,与所有View
树中与父级匹配的对象,如果顶层设置为静态大小,则整个Dialog
会改变尺寸。但如果顶层设置为WRAP_CONTENT
,所有其余的View
树中的物体仍然是抬头看树“匹配他们的父母”,而不是低头看树“包装他们的内容”。
如何解决问题:
说白了就是改变LayoutParams.width
of all View
影响路径中的对象WRAP_CONTENT
.
我发现这只能在之后完成onStart
的生命周期步骤DialogFragment
叫做。所以onStart
的实现如下:
@Override
public void onStart() {
// This MUST be called first! Otherwise the view tweaking will not be present in the displayed Dialog (most likely overriden)
super.onStart();
forceWrapContent(myCustomView);
}
然后函数适当修改View
等级制度LayoutParams
:
protected void forceWrapContent(View v) {
// Start with the provided view
View current = v;
// Travel up the tree until fail, modifying the LayoutParams
do {
// Get the parent
ViewParent parent = current.getParent();
// Check if the parent exists
if (parent != null) {
// Get the view
try {
current = (View) parent;
} catch (ClassCastException e) {
// This will happen when at the top view, it cannot be cast to a View
break;
}
// Modify the layout
current.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
}
} while (current.getParent() != null);
// Request a layout to be re-done
current.requestLayout();
}
And here is the working result:
![enter image description here](https://i.stack.imgur.com/pSCmZ.png)
这让我很困惑为什么整个Dialog
不想成为WRAP_CONTENT
具有明确的minWidth
设置为处理适合默认大小的所有情况,但我确信这样做是有充分理由的(我有兴趣听到它)。