如何设置DialogFragment的宽度和高度?

Adi*_*ain 157 android android-fragments android-dialog android-dialogfragment

我指定我DialogFragment的布局在XML布局文件(让我们称之为layout_mydialogfragment.xml),它layout_widthlayout_height属性,特别是(为100dp每个假设).然后我在DialogFragment的onCreateView(...)方法中扩充这个布局,如下所示:

View view = inflater.inflate(R.layout.layout_mydialogfragment, container, false);
Run Code Online (Sandbox Code Playgroud)

不幸的是,我发现当我的对话框(DialogFragment)出现时,它不尊重layout_widthlayout_height在其xml布局文件中指定(并且我的对话框根据内容收缩或扩展可变).任何人都知道我是否或如何让我的对话框尊重layout_widthlayout_height在其xml布局文件中指定?目前我必须在DialogFragment的onResume()方法中再次指定对话框的宽度和高度,如下所示......

getDialog().getWindow().setLayout(width, height);
Run Code Online (Sandbox Code Playgroud)

...因此,不可取的是,必须记住在两个地方对对话框的宽度和高度进行任何改进.

小智 159

如果直接从资源值转换:

int width = getResources().getDimensionPixelSize(R.dimen.popup_width);
int height = getResources().getDimensionPixelSize(R.dimen.popup_height);        
getDialog().getWindow().setLayout(width, height);
Run Code Online (Sandbox Code Playgroud)

然后在对话框的布局中指定match_parent:

android:layout_width="match_parent"
android:layout_height="match_parent"
Run Code Online (Sandbox Code Playgroud)

你只需要担心一个地方(把它放在你的地方DialogFragment#onResume).它并不完美,但至少它适用于将RelativeLayout作为对话框布局文件的根目录.

  • 这对我来说很有用(Android 4.0+),一旦我意识到这必须在**onResume()`**,而不是'onCreateView()`.(我的根布局是包含在ScrollView中的RelativeLayout.) (60认同)
  • 在某些情况下很有用:使用整个屏幕宽度:`int width = getResources().getDisplayMetrics().widthPixels` (14认同)
  • Jonik为+1.-1为理查德.我总是使用支持片段,从来没有能够在`onCreateDialog()`中使用它.需要在`onResume()`中. (5认同)
  • 这个答案在我的情况下不起作用(对于DialogFragment).我不得不使用FragmentLayout params来改变显示窗口的大小. (3认同)
  • 我必须将我的布局包装成`RelativeLayout`并且它帮助了我.非常感谢解决方案 - 它为我节省了很多时间. (3认同)

jma*_*ate 126

我最终覆盖Fragment.onResume()并从底层对话框中获取属性,然后在那里设置宽度/高度参数.我将最外面的布局高度/宽度设置为match_parent.请注意,此代码似乎也遵循我在xml布局中定义的边距.

@Override
public void onResume() {
    super.onResume();
    ViewGroup.LayoutParams params = getDialog().getWindow().getAttributes();
    params.width = LayoutParams.MATCH_PARENT;
    params.height = LayoutParams.MATCH_PARENT;
    getDialog().getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢 !这个对我有用 !此外,这是一种优雅的方式. (2认同)
  • 这是最好的解决方案。您甚至可以将像素的特定值与MATCH_PARENT或WRAP_CONTENT一起使用。 (2认同)

Jos*_*_GD 93

我有一个固定大小的DialogFragment在XML主布局中定义了以下内容(在我的例子中是LinearLayout):

android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="1000dp"
android:minHeight="450dp"
Run Code Online (Sandbox Code Playgroud)

  • 我发现我需要Honeycomb的midWidth和minHeight - 但不是ICS. (4认同)
  • 乍一看,这似乎有效,但可能应该避免。根据设备宽度,视图将继续离开屏幕,因此如果右下角有按钮,它们将不会出现。 (2认同)

小智 51

在我的案例中唯一有用的是这里提出的解决方案:http://adilatwork.blogspot.mx/2012/11/android-dialogfragment-dialog-sizing.html

来自Adil博文的片段:

@Override
public void onStart()
{
  super.onStart();

  // safety check
  if (getDialog() == null)
    return;

  int dialogWidth = ... // specify a value here
  int dialogHeight = ... // specify a value here

  getDialog().getWindow().setLayout(dialogWidth, dialogHeight);

  // ... other stuff you want to do in your onStart() method
}
Run Code Online (Sandbox Code Playgroud)

  • @ 2943 - 只是因为不能保证`Dialog`(`DialogFragment`的孩子)在请求时可用.当我们调用`getDialog()`时,Android可能会返回null. (3认同)

jpm*_*sta 42

控制DialogFragment宽度和高度的一种方法是确保其对话框尊重视图的宽度和高度(如果它们的值)WRAP_CONTENT.

运用 ThemeOverlay.AppCompat.Dialog

实现此目的的一种简单方法是使用ThemeOverlay.AppCompat.DialogAndroid支持库中包含的样式.

DialogFragmentDialog:

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    Dialog dialog = new Dialog(getContext(), R.style.ThemeOverlay_AppCompat_Dialog);
    dialog.setContentView(view);
    return dialog;
}
Run Code Online (Sandbox Code Playgroud)

DialogFragmentAlertDialog(警告:) minHeight="48dp":

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_AppCompat_Dialog);
    builder.setView(view);
    return builder.create();
}
Run Code Online (Sandbox Code Playgroud)

您还可以ThemeOverlay.AppCompat.Dialog在创建对话框时将其添加到应用程序的xml主题中,将其设置为默认主题.
要小心,因为许多对话框确实需要默认的最小宽度才能看起来很好.

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- For Android Dialog. -->
    <item name="android:dialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>

    <!-- For Android AlertDialog. -->
    <item name="android:alertDialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>

    <!-- For AppCompat AlertDialog. -->
    <item name="alertDialogTheme">@style/ThemeOverlay.AppCompat.Dialog</item>

    <!-- Other attributes. -->
</style>
Run Code Online (Sandbox Code Playgroud)

DialogFragmentDialog,利用android:dialogTheme:

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    Dialog dialog = new Dialog(getContext());
    dialog.setContentView(view);
    return dialog;
}
Run Code Online (Sandbox Code Playgroud)

DialogFragmentAlertDialog,使得使用android:alertDialogThemealertDialogTheme(警告:minHeight="48dp"):

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
    builder.setView(view);
    return builder.create();
}
Run Code Online (Sandbox Code Playgroud)

奖金

在较旧的Android API上,Dialogs似乎有一些宽度问题,因为它们的标题(即使你没有设置).
如果您不想使用ThemeOverlay.AppCompat.Dialog样式并且您Dialog不需要标题(或具有自定义标题),您可能希望禁用它:

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    Dialog dialog = new Dialog(getContext());
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setContentView(view);
    return dialog;
}
Run Code Online (Sandbox Code Playgroud)

过时的答案在大多数情况下都不起作用

我试图让对话框尊重我的布局的宽度和高度,而不是以编程方式指定固定大小.

我想到了android:windowMinWidthMinorandroid:windowMinWidthMajor导致了这个问题.即使他们没有在我的主题包括Activity或者Dialog,他们仍然被应用到Activity主题,不知何故.

我提出了三种可能的解决方案.

解决方案1:创建自定义对话框主题,并在创建对话框时使用它DialogFragment.

<style name="Theme.Material.Light.Dialog.NoMinWidth" parent="android:Theme.Material.Light.Dialog">
    <item name="android:windowMinWidthMinor">0dip</item>
    <item name="android:windowMinWidthMajor">0dip</item>
</style>
Run Code Online (Sandbox Code Playgroud)
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new Dialog(getActivity(), R.style.Theme_Material_Light_Dialog_NoMinWidth);
}
Run Code Online (Sandbox Code Playgroud)

解决方法2:创建一个使用自定义主题ContextThemeWrapper,将作为Context该对话框.如果您不想创建自定义对话框主题(例如,当您要使用指定的主题时),请使用此选项android:dialogTheme.

<style name="Theme.Window.NoMinWidth" parent="">
    <item name="android:windowMinWidthMinor">0dip</item>
    <item name="android:windowMinWidthMajor">0dip</item>
</style>
Run Code Online (Sandbox Code Playgroud)
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new Dialog(new ContextThemeWrapper(getActivity(), R.style.Theme_Window_NoMinWidth), getTheme());
}
Run Code Online (Sandbox Code Playgroud)

解决方案3(带有AlertDialog):强制执行android:windowMinWidthMinorandroid:windowMinWidthMajor进入ContextThemeWrapper创建者AlertDialog$Builder.

<style name="Theme.Window.NoMinWidth" parent="">
    <item name="android:windowMinWidthMinor">0dip</item>
    <item name="android:windowMinWidthMajor">0dip</item>
</style>
Run Code Online (Sandbox Code Playgroud)
@Override
public final Dialog onCreateDialog(Bundle savedInstanceState) {
    View view = new View(); // Inflate your view here.
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    builder.setView(view);
    // Make sure the dialog width works as WRAP_CONTENT.
    builder.getContext().getTheme().applyStyle(R.style.Theme_Window_NoMinWidth, true);
    return builder.create();
}
Run Code Online (Sandbox Code Playgroud)

  • 我真的不知道为什么这不是公认的答案.这实际上是唯一有效且不是黑客的答案(我主要是为你的第一个解决方案而言). (4认同)

rmi*_*lle 35

陷阱#13:DialogFragment布局

这真的麻木了.

创建a时DialogFragment,您可以选择覆盖onCreateView(传递a ViewGroup以将.xml布局附加到),或者onCreateDialog不会.

你不能覆盖这两种方法,因为你很可能会混淆Android的时间或对话框的布局是否膨胀!WTF?

是否覆盖OnCreateDialogOnCreateView取决于您打算如何使用对话框的选择.

  • 如果要在窗口中启动对话框(正常行为),则需要覆盖OnCreateDialog.
  • 如果您打算在现有的UI布局中嵌入对话框片段(FAR不常见),那么您应该覆盖OnCreateView.

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

onCreateDialog 疯狂

因此,您将覆盖onCreateDialogDialogFragment创建AlertDialog要在窗口中显示的自定义实例.凉.但请记住,onCreateDialog收到no ViewGroup以将自定义.xml布局附加.没问题,你只需传递nullinflate方法.

让疯狂开始吧.

当您覆盖时onCreateDialog,Android COMPLETELY忽略您膨胀的.xml布局的根节点的几个属性.这包括但可能不限于:

  • background_color
  • layout_gravity
  • layout_width
  • layout_height

这几乎是滑稽的,因为你需要设置layout_widthlayout_heightEVERY .XML布局或Android Studio会拍你的耻辱一个可爱的小红色徽章.

只是这个 DialogFragment让我想要呕吐.我可以写一本充满Android陷阱和snafus的小说,但这是一个最内心的.

为了恢复理智,首先,我们声明一种样式来恢复JUST 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>
Run Code Online (Sandbox Code Playgroud)

上面的样式继承自Dialogs的基本主题(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();
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码会让你AlertDialog看起来像个样子AlertDialog.也许这足够好了.

但等等,还有更多!

如果你想设置一个SPECIFIC layout_widthlayout_height你的AlertDialog时间(非常可能),那么猜猜看,你还没有完成!

当你意识到如果你试图设置一个特定的layout_widthlayout_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>
Run Code Online (Sandbox Code Playgroud)

要设置SPECIFIC窗口的宽度或高度,您可以继续使用整个'nuther方法并处理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);
}
Run Code Online (Sandbox Code Playgroud)

许多人都遵循Android的一个不好的例子,WindowManager.LayoutParams即更加通用ViewGroup.LayoutParams,只是向右转,然后再ViewGroup.LayoutParams回到WindowManager.LayoutParams几行.有效的Java被诅咒,除了使代码更难破译之外,不必要的铸造提供了许多东西.

附注:LayoutParamsAndroid SDK 中有两次重复- 这是一个极其糟糕的设计的完美示例.

综上所述

对于DialogFragment覆盖的s onCreateDialog:

  • 要恢复标准AlertDialog外观,请创建一个设置background_color= transparentlayout_gravity=的center样式并应用该样式onCreateDialog.
  • 设置特定layout_width和/或以layout_height编程方式onResume执行LayoutParams
  • 为了保持理智,请尽量不要考虑Android SDK.

  • 读这个答案让我想哭. (11认同)
  • 有人可以将此答案勾选为正确吗?对我帮助很大!!!! (3认同)
  • 伙计,你准确地描述了我现在正在经历的事情. (2认同)
  • 安卓很烂。感觉你哥 一切都需要上下文,应用程序进程终止,某些事情缺乏支持库,列表还在继续 (2认同)

And*_*rey 13

当我需要使DialogFragment更宽一点时,我设置minWidth:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minWidth="320dp"
    ... />
Run Code Online (Sandbox Code Playgroud)


N1h*_*1hk 10

我看不出一个令人信服的理由来覆盖onResumeonStart设置的宽度和高度Window范围内DialogFragmentDialog-这些特定的生命周期方法可以得到反复和不必要的称为执行该调整的代码不止一次因之类的多窗口切换,backgrounding然后将应用程序置于前台,依此类推。这种重复的后果相当微不足道,但为什么要满足于此呢?

在重写的onActivityCreated()方法中设置宽度/高度将是一种改进,因为实际上每个DialogFragment. 例如:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    Window window = getDialog().getWindow();
    assert window != null;

    WindowManager.LayoutParams layoutParams = window.getAttributes();
    layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
    window.setAttributes(layoutParams);
}
Run Code Online (Sandbox Code Playgroud)

上面我只是将宽度设置为match_parent与设备方向无关。如果您希望您的横向对话框不那么宽,您可以getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT事先检查是否。


小智 6

最外层布局中的尺寸在对话框中不起作用.您可以添加一个布局,其中设置尺寸位于最外层.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<LinearLayout
    android:layout_width="xxdp"
    android:layout_height="xxdp"
    android:orientation="vertical">

</LinearLayout>
Run Code Online (Sandbox Code Playgroud)


小智 5

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

int width = activity.getResources().getDisplayMetrics().widthPixels;
int height = activity.getResources().getDisplayMetrics().heightPixels;
content.setLayoutParams(new LinearLayout.LayoutParams(width, height));
Run Code Online (Sandbox Code Playgroud)


Nam*_*ace 5

这是在xml中设置DialogFragment宽度/高度的方法。只需将viewHierarchy包装在具有透明背景的Framelayout中(任何布局都可以使用)。

透明背景似乎是一个特殊的标志,因为这样做时,它会自动将frameLayout的子项在窗口中居中。您的片段后面仍将全屏变暗,表明您的片段是活动元素。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/transparent">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:background="@color/background_material_light">

      .....
Run Code Online (Sandbox Code Playgroud)


Ste*_*oM5 5

您可以使用百分比表示宽度。

<style name="Theme.Holo.Dialog.MinWidth">
<item name="android:windowMinWidthMajor">70%</item>
Run Code Online (Sandbox Code Playgroud)

我在这个例子中使用了 Holo 主题。


Qad*_*ain 5

这是 kotlin 版本

    override fun onResume() {
        super.onResume()

        val params:ViewGroup.LayoutParams = dialog.window.attributes
        params.width = LinearLayout.LayoutParams.MATCH_PARENT
        params.height = LinearLayout.LayoutParams.MATCH_PARENT
        dialog.window.attributes = params as android.view.WindowManager.LayoutParams
    }
Run Code Online (Sandbox Code Playgroud)


Coo*_*ind 5

在我的情况下,DialogFragmentFragment. 它DialogFragment基于 XML 布局,而不是AlertDialog. 我的错误是将对话框片段添加FragmentManager为通常的片段:

fragmentManager?.beginTransaction()?.run {
    replace(R.id.container, MyDialogFragment.newInstance(), MyDialogFragment.TAG)
    addToBackStack(MyDialogFragment.TAG)
}?.commitAllowingStateLoss()
Run Code Online (Sandbox Code Playgroud)

相反,我需要show对话片段:

val dialogFragment = MyDialogFragment.newInstance()
fragmentManager?.let { dialogFragment.show(it, MyDialogFragment.TAG) }
Run Code Online (Sandbox Code Playgroud)

经过一些编辑(我ViewPager2在布局中),对话框片段变得太窄了:

在此处输入图片说明

我使用了N1hk的解决方案:

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

    dialog?.window?.attributes?.width = ViewGroup.LayoutParams.MATCH_PARENT
    dialog?.window?.attributes?.height = ViewGroup.LayoutParams.MATCH_PARENT
}
Run Code Online (Sandbox Code Playgroud)

现在它定义了宽度和高度,而不是完整的活动大小。

我想说一下onCreateViewonCreateDialog。如果你有一个基于布局的对话框片段,你可以使用这两种方法中的任何一种。

  1. 如果您使用onCreateView,那么您应该使用onActivityCreated来设置宽度。

  2. 如果使用onCreateDialog代替onCreateView,则可以在那里设置参数。onActivityCreated将不需要。

    覆盖乐趣 onCreateDialog(savedInstanceState: Bundle?): Dialog { super.onCreateDialog(savedInstanceState)

     val view = activity?.layoutInflater?.inflate(R.layout.your_layout, null)
    
     val dialogBuilder = MaterialAlertDialogBuilder(context!!).apply { // Or AlertDialog.Builder(context!!).apply
         setView(view)
         // setCancelable(false)
     }
    
     view.text_view.text = "Some text"
    
     val dialog = dialogBuilder.create()
     // You can access dialog.window here, if needed.
    
     return dialog
    
    Run Code Online (Sandbox Code Playgroud)

    }


Rob*_*bin 5

我采纳了 @rmirabella 的答案并更新了它以处理高度:

private fun DialogFragment.setSize(widthPercentage: Int, heightPercentage: Int) {
    val newWidth = widthPercentage.toFloat() / 100
    val newHeight = heightPercentage.toFloat() / 100
    val dm = Resources.getSystem().displayMetrics
    val rect = dm.run { Rect(0, 0, widthPixels, heightPixels) }
    val percentWidth = rect.width() * newWidth
    val percentHeight = rect.height() * newHeight
    dialog?.window?.setLayout(percentWidth.toInt(), percentHeight.toInt())
}
Run Code Online (Sandbox Code Playgroud)

然后在你的DialogFragmentin 或 after中onStart()

override fun onStart() {
    super.onStart()
    setSize(
        widthPercentage = 100,
        heightPercentage = 80
    )
}
Run Code Online (Sandbox Code Playgroud)