Android 如何设置 DialogFragment 的宽度和高度?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12478520/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set DialogFragment's width and height?
提问by Adil Hussain
I specify the layout of my DialogFragment in an xml layout file (let's call it layout_mydialogfragment.xml
), and its layout_width
and layout_height
attributes particularly (to be 100dp
each let's say). I then inflate this layout in my DialogFragment's onCreateView(...)
method as follows:
我在 xml 布局文件中指定了我的 DialogFragment 的布局(我们称之为layout_mydialogfragment.xml
),特别是它的layout_width
和layout_height
属性(100dp
让我们说每个人)。然后我在我的 DialogFragmentonCreateView(...)
方法中扩展这个布局,如下所示:
View view = inflater.inflate(R.layout.layout_mydialogfragment, container, false);
Unfortunately, I find that when my dialog (DialogFragment) appears, it does not respect the layout_width
and layout_height
specified in its xml layout file (and my dialog shrinks or expands variably depending on content). Anyone know whether or how I can get my dialog to respect the layout_width
and layout_height
specified in its xml layout file? At the moment I'm having to specify the width and height of my dialog again in my DialogFragment's onResume()
method as follows...
不幸的是,我发现当我的对话框 (DialogFragment) 出现时,它不遵守其 xml 布局文件中指定的layout_width
和layout_height
(并且我的对话框根据内容不同地缩小或扩展)。任何人都知道我是否或如何让我的对话框尊重其 xml 布局文件中指定的layout_width
和layout_height
?目前,我必须在 DialogFragment 的onResume()
方法中再次指定对话框的宽度和高度,如下所示...
getDialog().getWindow().setLayout(width, height);
... And thus, undesirably, have to remember to make any future changes to the dialog's width and height in two places.
......因此,不希望出现的是,必须记住在两个地方对对话框的宽度和高度进行任何未来的更改。
采纳答案by Blix247
If you convert directly from resources values:
如果直接从资源值转换:
int width = getResources().getDimensionPixelSize(R.dimen.popup_width);
int height = getResources().getDimensionPixelSize(R.dimen.popup_height);
getDialog().getWindow().setLayout(width, height);
Then specify match_parent in your layout for the dialog:
然后在对话框的布局中指定 match_parent :
android:layout_width="match_parent"
android:layout_height="match_parent"
You only have to worry about one place (place it in your DialogFragment#onResume
). Its not perfect, but at least it works for having a RelativeLayout as the root of your dialog's layout file.
你只需要担心一个地方(把它放在你的DialogFragment#onResume
)。它并不完美,但至少它适用于将 RelativeLayout 作为对话框布局文件的根。
回答by jmaculate
I ended up overriding Fragment.onResume()
and grabbing the attributes from the underlying dialog, then setting width/height params there. I set the outermost layout height/width to match_parent
. Note that this code seems to respect the margins I defined in the xml layout as well.
我最终覆盖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);
}
回答by Jose_GD
I got a fixed size DialogFragment defining the following in the XML main layout (LinearLayout in my case):
我得到了一个固定大小的 DialogFragment,它在 XML 主布局中定义了以下内容(在我的例子中是 LinearLayout):
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="1000dp"
android:minHeight="450dp"
回答by Rodrigo
The only thing that worked in my case was the solution pointed here: http://adilatwork.blogspot.mx/2012/11/android-dialogfragment-dialog-sizing.html
在我的情况下唯一有效的是这里指出的解决方案:http: //adilatwork.blogspot.mx/2012/11/android-dialogfragment-dialog-sizing.html
Snippet from Adil blog post:
来自 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
}
回答by jpmcosta
One way to control your DialogFragment
's width and height is to make sure its dialog respects your view's width and height if their value is WRAP_CONTENT
.
控制你DialogFragment
的宽度和高度的一种方法是确保它的对话框尊重你的视图的宽度和高度,如果它们的值为WRAP_CONTENT
。
Using ThemeOverlay.AppCompat.Dialog
使用 ThemeOverlay.AppCompat.Dialog
One simple way to achieve this is to make use of the ThemeOverlay.AppCompat.Dialog
style that's included in Android Support Library.
实现此目的的一种简单方法是利用ThemeOverlay.AppCompat.Dialog
Android 支持库中包含的样式。
DialogFragment
with Dialog
:
DialogFragment
与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(), R.style.ThemeOverlay_AppCompat_Dialog);
dialog.setContentView(view);
return dialog;
}
DialogFragment
with AlertDialog
(caveat: minHeight="48dp"
):
DialogFragment
与AlertDialog
(警告:)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();
}
You can also set ThemeOverlay.AppCompat.Dialog
as the default theme when creating your dialogs, by adding it to your app's xml theme.
Be careful, as many dialogs do need the default minimum width to look good.
您还可以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>
DialogFragment
with Dialog
, making use of android:dialogTheme
:
DialogFragment
用Dialog
,使得使用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;
}
DialogFragment
with AlertDialog
, making use of android:alertDialogTheme
or alertDialogTheme
(caveat: minHeight="48dp"
):
DialogFragment
与AlertDialog
,利用android:alertDialogTheme
或alertDialogTheme
(警告:)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();
}
Bonus
奖金
On Older Android APIs, Dialog
s seem to have some width issues, because of their title (even if you don't set one).
If you don't want to use ThemeOverlay.AppCompat.Dialog
style and your Dialog
doesn't need a title (or has a custom one), you might want to disable it:
在较旧的 Android API 上,Dialog
s 似乎有一些宽度问题,因为它们的标题(即使您没有设置)。
如果您不想使用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;
}
Outdated answer, won't work in most cases
过时的答案,在大多数情况下不起作用
I was trying to make the dialog respect the width and height of my layout, without specifying a fixed size programmatically.
我试图让对话框尊重我的布局的宽度和高度,而不以编程方式指定固定大小。
I figured that android:windowMinWidthMinor
and android:windowMinWidthMajor
were causing the problem. Even though they were not included in the theme of my Activity
or Dialog
, they were still being applied to the Activity
theme, somehow.
我想到了这一点android:windowMinWidthMinor
,android:windowMinWidthMajor
并导致了问题。即使它们不包含在 myActivity
或的主题中Dialog
,它们仍然以Activity
某种方式应用于主题。
I came up with three possible solutions.
我想出了三种可能的解决方案。
Solution 1:create a custom dialog theme and use it when creating the dialog in the DialogFragment
.
解决方案一:创建自定义对话框主题,在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>
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new Dialog(getActivity(), R.style.Theme_Material_Light_Dialog_NoMinWidth);
}
Solution 2:create a custom theme to be used in a ContextThemeWrapper
that will serve as Context
for the dialog. Use this if you don't want to create a custom dialog theme (for instance, when you want to use the theme specified by android:dialogTheme
).
解决方法2:创建一个使用自定义主题ContextThemeWrapper
,将作为Context
该对话框。如果您不想创建自定义对话框主题(例如,当您想使用由 指定的主题时),请使用此选项android:dialogTheme
。
<style name="Theme.Window.NoMinWidth" parent="">
<item name="android:windowMinWidthMinor">0dip</item>
<item name="android:windowMinWidthMajor">0dip</item>
</style>
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new Dialog(new ContextThemeWrapper(getActivity(), R.style.Theme_Window_NoMinWidth), getTheme());
}
Solution 3 (with an AlertDialog
):enforce android:windowMinWidthMinor
and android:windowMinWidthMajor
into the ContextThemeWrapper
created by the AlertDialog$Builder
.
解决方案 3(带有AlertDialog
):强制android:windowMinWidthMinor
并android:windowMinWidthMajor
进入ContextThemeWrapper
由AlertDialog$Builder
.
<style name="Theme.Window.NoMinWidth" parent="">
<item name="android:windowMinWidthMinor">0dip</item>
<item name="android:windowMinWidthMajor">0dip</item>
</style>
@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();
}
回答by rmirabelle
Gotcha #13: DialogFragment
Layouts
陷阱 #13:DialogFragment
布局
It's sort of mind numbing really.
真的有点伤脑筋。
When creating a DialogFragment
, you can choose to override onCreateView
(which passes a ViewGroup
to attach your .xml layout to) or onCreateDialog
, which does not.
创建 时DialogFragment
,您可以选择覆盖onCreateView
(传递 aViewGroup
以将 .xml 布局附加到)或onCreateDialog
不覆盖。
You mustn't override both methods tho, because you will very likely confuse Android as to when or if your dialog's layout was inflated! WTF?
您不能覆盖这两种方法,因为您很可能会混淆 Android 何时或是否膨胀对话框的布局!跆拳道?
The choice of whether to override OnCreateDialog
or OnCreateView
depends on how you intend to use the dialog.
选择是覆盖OnCreateDialog
还是OnCreateView
取决于您打算如何使用该对话框。
- If you will launch the dialog in a window (the normal behavior), you are expected to override
OnCreateDialog
. - If you intend to embed the dialog fragment within an existing UI layout (FAR less common), then you are expected to override
OnCreateView
.
- 如果您将在窗口中启动对话框(正常行为),您应该覆盖
OnCreateDialog
. - 如果您打算将对话框片段嵌入到现有的 UI 布局中(不太常见),那么您应该覆盖
OnCreateView
.
This is possibly the worst thing in the world.
这可能是世界上最糟糕的事情。
onCreateDialog
Insanity
onCreateDialog
疯狂
So, you're overriding onCreateDialog
in your DialogFragment
to create a customized instance of AlertDialog
to display in a window. Cool. But remember, onCreateDialog
receives no ViewGroup
to attach your custom .xml layout to. No problem, you simply pass null
to the inflate
method.
因此,您将覆盖onCreateDialog
您DialogFragment
的创建自定义实例AlertDialog
以在窗口中显示。凉爽的。但请记住,onCreateDialog
收到 noViewGroup
将您的自定义 .xml 布局附加到. 没问题,您只需传递null
给inflate
方法。
Let the madness begin.
让疯狂开始吧。
When you override onCreateDialog
, Android COMPLETELY IGNORESseveral attributes of the root node of the .xml Layout you inflate. This includes, but probably isn't limited to:
当您覆盖 时onCreateDialog
,Android完全忽略您膨胀的 .xml 布局的根节点的几个属性。这包括但可能不限于:
background_color
layout_gravity
layout_width
layout_height
background_color
layout_gravity
layout_width
layout_height
This is almost comical, as you are required to set the
layout_width
andlayout_height
of EVERY .xml Layout or Android Studio will slap you with a nice little red badge of shame.
这几乎是可笑的,因为您需要设置每个 .xml 布局的
layout_width
和layout_height
,否则 Android Studio 会给您一个漂亮的红色小徽章。
Just the wordDialogFragment
makes me want to puke. I could write a novel filled with Android gotchas and snafus, but this one is one of the most insideous.
光是一句话DialogFragment
就想吐。我可以写一本充满 Android 陷阱和混乱的小说,但这是最内行的小说之一。
To return to sanity, first, we declare a style to restore JUST the background_color
and layout_gravity
we expect:
为了恢复理智,首先,我们声明一个样式来恢复 JUSTbackground_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>
The style above inherits from the base theme for Dialogs (in the AppCompat
theme in this example).
上面的样式继承自 Dialogs 的基本主题(AppCompat
在本例中的主题中)。
Next, we applythe style programmatically to put back the values Android just tossed aside and to restore the standard AlertDialog
look and feel:
接下来,我们以编程方式应用样式来放回 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();
}
}
The code above will make your AlertDialog
look like an AlertDialog
again. Maybe this is good enough.
上面的代码会让你AlertDialog
看起来像一个AlertDialog
。也许这已经足够了。
But wait, there's more!
但是等等,还有更多!
If you're looking to set a SPECIFIClayout_width
or layout_height
for your AlertDialog
when it's shown (very likely), then guess what, you ain't done yet!
如果你正在寻找设置特定layout_width
或layout_height
您AlertDialog
时,它的显示(极有可能),那么你猜怎么着,你还没有完成!
The hilarity continues as you realize that if you attempt to set a specific layout_width
or layout_height
in your fancy new style, Android will completely ignore that, too!:
当你意识到如果你试图设置一个特定的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>
To set a SPECIFIC window width or height, you get to head on over to a whole 'nuther method and deal with LayoutParams
:
要设置特定的窗口宽度或高度,您可以使用整个 '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);
}
Many folks follow Android's bad example of casting
WindowManager.LayoutParams
up to the more generalViewGroup.LayoutParams
, only to turn right around and castViewGroup.LayoutParams
back down toWindowManager.LayoutParams
a few lines later. Effective Java be damned, that unnecessary casting offers NOTHING other than making the code even harder to decipher.Side note: There are some TWENTY repetitions of
LayoutParams
across the Android SDK - a perfect example of radically poor design.
许多人遵循 Android 的坏例子,将
WindowManager.LayoutParams
其转换为更一般的ViewGroup.LayoutParams
,只是右转并稍后ViewGroup.LayoutParams
返回到WindowManager.LayoutParams
几行。该死的有效 Java,这种不必要的转换只会使代码更难破译。旁注:
LayoutParams
Android SDK 中有一些 200 次重复——这是设计极差的完美例子。
In Summary
总之
For DialogFragment
s that override onCreateDialog
:
对于DialogFragment
覆盖的 s onCreateDialog
:
- To restore the standard
AlertDialog
look and feel, create a style that setsbackground_color
=transparent
andlayout_gravity
=center
and apply that style inonCreateDialog
. - To set a specific
layout_width
and/orlayout_height
, do it programmatically inonResume
withLayoutParams
- To maintain sanity, try not to think about the Android SDK.
- 要恢复标准的
AlertDialog
外观和感觉,请创建一个设置background_color
=transparent
和layout_gravity
= 的center
样式并将该样式应用到onCreateDialog
. - 要设置特定的
layout_width
和/或layout_height
,请以编程方式onResume
使用LayoutParams
- 为了保持理智,尽量不要考虑 Android SDK。
回答by Andrey
When I need to make the DialogFragment a bit wider I'm setting minWidth:
当我需要使 DialogFragment 更宽时,我正在设置 minWidth:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="320dp"
... />
回答by N1hk
I don't see a compelling reason to override onResume
or onStart
to set the width and height of the Window
within DialogFragment
's Dialog
-- these particular lifecycle methods can get called repeatedly and unnecessarily execute that resizing code more than once due to things like multi window switching, backgrounding then foregrounding the app, and so on. The consequences of that repetition are fairly trivial, but why settle for that?
我看不出一个令人信服的理由来覆盖onResume
或onStart
设置的宽度和高度Window
范围内DialogFragment
的Dialog
-这些特定的生命周期方法可以得到反复和不必要的称为执行该调整的代码不止一次因之类的多窗口切换,backgrounding然后将应用程序置于前台,依此类推。这种重复的后果相当微不足道,但为什么要满足于此呢?
Setting the width/height instead within an overridden onActivityCreated()
method will be an improvement because this method realistically only gets called once per instance of your DialogFragment
. For example:
在重写的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);
}
Above I just set the width to be match_parent
irrespective of device orientation. If you want your landscape dialog to not be so wide, you can do a check of whether getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT
beforehand.
上面我只是将宽度设置为match_parent
与设备方向无关。如果您希望您的横向对话框不那么宽,您可以getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT
事先检查是否。
回答by Kelly
The dimension in outermost layout doesn't work in dialog. You can add a layout where set dimension below the outermost.
最外层布局中的尺寸在对话框中不起作用。您可以添加一个布局,其中在最外层下方设置尺寸。
<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>
回答by NameSpace
Here's a way to set DialogFragment width/height in xml. Just wrap your viewHierarchy in a Framelayout (any layout will work) with a transparent background.
这是一种在 xml 中设置 DialogFragment 宽度/高度的方法。只需将您的 viewHierarchy 包装在具有透明背景的 Framelayout(任何布局都可以)中。
A transparent background seems to be a special flag, because it automatically centers the frameLayout's child in the window when you do that. You will still get the full screen darkening behind your fragment, indicating your fragment is the active element.
透明背景似乎是一个特殊的标志,因为当您这样做时,它会自动将 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">
.....