假设我在一个名为my_dialog_fragment.xml的xml布局文件中指定了我的DialogFragment的布局,并且我将其根视图的layout_width和layout_height值指定为固定值(例如100dp)。然后我在我的DialogFragment的onCreateView(…)方法中膨胀这个布局,如下所示:

View view = inflater.inflate(R.layout.my_dialog_fragment, container, false);

可悲的是,我发现当我的DialogFragment出现时,它不尊重layout_width和layout_height值在其xml布局文件中指定,而是根据其内容收缩或展开。有人知道我是否或如何得到我的DialogFragment尊重layout_width和layout_height值指定在其xml布局文件?目前,我必须在我的DialogFragment的onResume()方法中再次指定对话框的宽度和高度,如下所示:

getDialog().getWindow().setLayout(width, height);

这样做的问题是,我必须记住将来在两个地方对宽度和高度进行任何更改。


当前回答

更新2021

对于Kotlin用户,我设计了几个简单的扩展方法,可以将DialogFragment的宽度设置为屏幕宽度的百分比,或者接近全屏:

/**
 * Call this method (in onActivityCreated or later) to set 
 * the width of the dialog to a percentage of the current 
 * screen width.
 */
fun DialogFragment.setWidthPercent(percentage: Int) {
    val percent = percentage.toFloat() / 100
    val dm = Resources.getSystem().displayMetrics
    val rect = dm.run { Rect(0, 0, widthPixels, heightPixels) }
    val percentWidth = rect.width() * percent
    dialog?.window?.setLayout(percentWidth.toInt(), ViewGroup.LayoutParams.WRAP_CONTENT)
}

/**
 * Call this method (in onActivityCreated or later) 
 * to make the dialog near-full screen.
 */
fun DialogFragment.setFullScreen() {
    dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}

然后在你的DialogFragment中或onActivityCreated之后:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    setWidthPercent(85)
}

为子孙后代考虑一下这个答案的其余部分。

问题13:对话片段布局

这真的有点让人麻木。

当创建一个DialogFragment时,你可以选择覆盖onCreateView(它传递一个ViewGroup来附加你的.xml布局)或onCreateDialog,后者没有。

但是你不能同时覆盖这两个方法,因为你很可能会让Android搞不清楚你的对话框布局是否被夸大了!WTF ?

是否覆盖OnCreateView或OnCreateDialog的选择取决于你打算如何使用对话框。

如果你打算允许DialogFragment来控制它自己内部对话框的呈现,那么你需要重写OnCreateView。 如果你打算手动控制DialogFragment的对话框将如何呈现,你需要重写OnCreateDialog。

这可能是世界上最糟糕的事情了。

onCreateDialog疯狂

因此,您正在重写DialogFragment中的onCreateDialog以创建一个自定义的AlertDialog实例以显示在窗口中。酷。但是请记住,onCreateDialog没有接收ViewGroup来附加您的自定义.xml布局。没问题,您只需将null传递给充气方法。

让疯狂开始吧。

当你重写onCreateDialog时,Android完全忽略了你膨胀的.xml布局的根节点的几个属性。这包括但不限于:

background_color layout_gravity layout_width layout_height

这几乎是滑稽的,因为你被要求设置每一个.xml布局的layout_width和layout_height或Android Studio将扇你一个漂亮的小红色耻辱徽章。

光是DialogFragment这个词就让我想吐。我可以写一本充满Android陷阱和混乱的小说,但这是最阴险的一个。

为了回归理智,首先,我们声明一个样式来恢复我们期望的background_color和layout_gravity:

<style name="MyAlertDialog" parent="Theme.AppCompat.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:layout_gravity">center</item>
</style>

上面的样式继承自对话框的基本主题(在本例中的AppCompat主题中)。

接下来,我们通过编程的方式应用样式来放回Android刚刚丢弃的值,并恢复标准的AlertDialog外观:

public class MyDialog extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        View layout = getActivity().getLayoutInflater().inflate(R.layout.my_dialog_layout, null, false);
        assert layout != null;
        //build the alert dialog child of this fragment
        AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
        //restore the background_color and layout_gravity that Android strips
        b.getContext().getTheme().applyStyle(R.style.MyAlertDialog, true);
        b.setView(layout);
        return b.create();
    }
}

上面的代码将使您的AlertDialog看起来像一个AlertDialog。也许这就足够了。

但是等等,还有更多!

如果你正在为你的AlertDialog设置一个特定的layout_width或layout_height,当它显示(很可能),然后你猜什么,你还没有完成!

有趣的是,当你意识到如果你试图在你的花哨的新样式中设置一个特定的layout_width或layout_height时,Android也会完全忽略它!:

<style name="MyAlertDialog" parent="Theme.AppCompat.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:layout_gravity">center</item>
    <!-- NOPE!!!!! --->
    <item name="android:layout_width">200dp</item>
    <!-- NOPE!!!!! --->
    <item name="android:layout_height">200dp</item>
</style>

要设置一个特定的窗口宽度或高度,你需要使用一个完整的方法来处理LayoutParams:

@Override
public void onResume() {
    super.onResume();
    Window window = getDialog().getWindow();
    if(window == null) return;
    WindowManager.LayoutParams params = window.getAttributes();
    params.width = 400;
    params.height = 400;
    window.setAttributes(params);
}

许多人效仿Android的坏例子,使用WindowManager。LayoutParams到更通用的ViewGroup。LayoutParams,只是为了右转并施放ViewGroup。LayoutParams返回到WindowManager。几行之后的LayoutParams。有效的Java见鬼去吧,这种不必要的强制转换除了使代码更难破译之外,什么也没有提供。

旁注:在Android SDK中有大约20个重复的LayoutParams——这是一个非常糟糕的设计的完美例子。

总之

对于覆盖onCreateDialog的DialogFragments:

要恢复标准AlertDialog的外观和感觉,创建一个设置background_color = transparent和layout_gravity = center的样式,并在onCreateDialog中应用该样式。 要设置特定的layout_width和/或layout_height,可以在onResume中通过LayoutParams编程来实现 为了保持理智,尽量不要去想Android SDK。

其他回答

这将会非常有效。

@Override
public void onResume() {
    super.onResume();
    Window window = getDialog().getWindow();
    if(window == null) return;
    WindowManager.LayoutParams params = window.getAttributes();
    params.width = 400;
    params.height = 400;
    window.setAttributes(params);
}
@Override
public void onStart() {
    super.onStart();
    Dialog dialog = getDialog();
    if (dialog != null)
    {
        dialog.getWindow().setLayout(-1, -2);
        dialog.getWindow().getAttributes().windowAnimations = R.style.DialogAnimation;
        Window window = getDialog().getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.dimAmount = 1.0f;
        window.setAttributes(params);
        window.setBackgroundDrawableResource(android.R.color.transparent);
    }
}

我修复了它设置根元素布局参数。

int width = activity.getResources().getDisplayMetrics().widthPixels;
int height = activity.getResources().getDisplayMetrics().heightPixels;
content.setLayoutParams(new LinearLayout.LayoutParams(width, height));

早期的一个解决方案几乎起作用了。我尝试了一些稍微不同的方法,结果对我有用。

(一定要看他的解决方案) 这就是他的解决办法。点击这里 除了builder.getContext(). gettheme (). applystyle (R.style。Theme_Window_NoMinWidth,真正的);

我把它改成

 @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {


        // Use the Builder class for convenient dialog construction
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        // Get layout inflater
        LayoutInflater layoutInflater = getActivity().getLayoutInflater();

        // Set layout by setting view that is returned from inflating the XML layout
        builder.setView(layoutInflater.inflate(R.layout.dialog_window_layout, null));


        AlertDialog dialog = builder.create();

        dialog.getContext().setTheme(R.style.Theme_Window_NoMinWidth);

最后一行是真正的不同之处。

更新2021

对于Kotlin用户,我设计了几个简单的扩展方法,可以将DialogFragment的宽度设置为屏幕宽度的百分比,或者接近全屏:

/**
 * Call this method (in onActivityCreated or later) to set 
 * the width of the dialog to a percentage of the current 
 * screen width.
 */
fun DialogFragment.setWidthPercent(percentage: Int) {
    val percent = percentage.toFloat() / 100
    val dm = Resources.getSystem().displayMetrics
    val rect = dm.run { Rect(0, 0, widthPixels, heightPixels) }
    val percentWidth = rect.width() * percent
    dialog?.window?.setLayout(percentWidth.toInt(), ViewGroup.LayoutParams.WRAP_CONTENT)
}

/**
 * Call this method (in onActivityCreated or later) 
 * to make the dialog near-full screen.
 */
fun DialogFragment.setFullScreen() {
    dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}

然后在你的DialogFragment中或onActivityCreated之后:

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    setWidthPercent(85)
}

为子孙后代考虑一下这个答案的其余部分。

问题13:对话片段布局

这真的有点让人麻木。

当创建一个DialogFragment时,你可以选择覆盖onCreateView(它传递一个ViewGroup来附加你的.xml布局)或onCreateDialog,后者没有。

但是你不能同时覆盖这两个方法,因为你很可能会让Android搞不清楚你的对话框布局是否被夸大了!WTF ?

是否覆盖OnCreateView或OnCreateDialog的选择取决于你打算如何使用对话框。

如果你打算允许DialogFragment来控制它自己内部对话框的呈现,那么你需要重写OnCreateView。 如果你打算手动控制DialogFragment的对话框将如何呈现,你需要重写OnCreateDialog。

这可能是世界上最糟糕的事情了。

onCreateDialog疯狂

因此,您正在重写DialogFragment中的onCreateDialog以创建一个自定义的AlertDialog实例以显示在窗口中。酷。但是请记住,onCreateDialog没有接收ViewGroup来附加您的自定义.xml布局。没问题,您只需将null传递给充气方法。

让疯狂开始吧。

当你重写onCreateDialog时,Android完全忽略了你膨胀的.xml布局的根节点的几个属性。这包括但不限于:

background_color layout_gravity layout_width layout_height

这几乎是滑稽的,因为你被要求设置每一个.xml布局的layout_width和layout_height或Android Studio将扇你一个漂亮的小红色耻辱徽章。

光是DialogFragment这个词就让我想吐。我可以写一本充满Android陷阱和混乱的小说,但这是最阴险的一个。

为了回归理智,首先,我们声明一个样式来恢复我们期望的background_color和layout_gravity:

<style name="MyAlertDialog" parent="Theme.AppCompat.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:layout_gravity">center</item>
</style>

上面的样式继承自对话框的基本主题(在本例中的AppCompat主题中)。

接下来,我们通过编程的方式应用样式来放回Android刚刚丢弃的值,并恢复标准的AlertDialog外观:

public class MyDialog extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        View layout = getActivity().getLayoutInflater().inflate(R.layout.my_dialog_layout, null, false);
        assert layout != null;
        //build the alert dialog child of this fragment
        AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
        //restore the background_color and layout_gravity that Android strips
        b.getContext().getTheme().applyStyle(R.style.MyAlertDialog, true);
        b.setView(layout);
        return b.create();
    }
}

上面的代码将使您的AlertDialog看起来像一个AlertDialog。也许这就足够了。

但是等等,还有更多!

如果你正在为你的AlertDialog设置一个特定的layout_width或layout_height,当它显示(很可能),然后你猜什么,你还没有完成!

有趣的是,当你意识到如果你试图在你的花哨的新样式中设置一个特定的layout_width或layout_height时,Android也会完全忽略它!:

<style name="MyAlertDialog" parent="Theme.AppCompat.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:layout_gravity">center</item>
    <!-- NOPE!!!!! --->
    <item name="android:layout_width">200dp</item>
    <!-- NOPE!!!!! --->
    <item name="android:layout_height">200dp</item>
</style>

要设置一个特定的窗口宽度或高度,你需要使用一个完整的方法来处理LayoutParams:

@Override
public void onResume() {
    super.onResume();
    Window window = getDialog().getWindow();
    if(window == null) return;
    WindowManager.LayoutParams params = window.getAttributes();
    params.width = 400;
    params.height = 400;
    window.setAttributes(params);
}

许多人效仿Android的坏例子,使用WindowManager。LayoutParams到更通用的ViewGroup。LayoutParams,只是为了右转并施放ViewGroup。LayoutParams返回到WindowManager。几行之后的LayoutParams。有效的Java见鬼去吧,这种不必要的强制转换除了使代码更难破译之外,什么也没有提供。

旁注:在Android SDK中有大约20个重复的LayoutParams——这是一个非常糟糕的设计的完美例子。

总之

对于覆盖onCreateDialog的DialogFragments:

要恢复标准AlertDialog的外观和感觉,创建一个设置background_color = transparent和layout_gravity = center的样式,并在onCreateDialog中应用该样式。 要设置特定的layout_width和/或layout_height,可以在onResume中通过LayoutParams编程来实现 为了保持理智,尽量不要去想Android SDK。