我在xml布局文件中指定了我的DialogFragment的布局(让我们称之为layout_mydialogfragment.xml
),并特别指定其layout_width
和layout_height
属性(每个100dp
让我们说)。然后我在DialogFragment的onCreateView(...)
方法中扩充此布局,如下所示:
View view = inflater.inflate(R.layout.layout_mydialogfragment, container, false);
不幸的是,我发现当我的对话框(DialogFragment)出现时,它不尊重其xml布局文件中指定的layout_width
和layout_height
(我的对话框会根据内容缩小或扩展) 。任何人都知道我是否或如何让我的对话框尊重其xml布局文件中指定的layout_width
和layout_height
?目前我必须在DialogFragment的onResume()
方法中再次指定对话框的宽度和高度,如下所示......
getDialog().getWindow().setLayout(width, height);
...因此,不可取的是,必须记住在两个地方对对话框的宽度和高度进行任何改进。
答案 0 :(得分:145)
如果直接从资源值转换:
int width = getResources().getDimensionPixelSize(R.dimen.popup_width);
int height = getResources().getDimensionPixelSize(R.dimen.popup_height);
getDialog().getWindow().setLayout(width, height);
然后在对话框的布局中指定match_parent:
android:layout_width="match_parent"
android:layout_height="match_parent"
您只需要担心一个地方(将其放在DialogFragment#onResume
中)。它并不完美,但至少它适用于将RelativeLayout作为对话框布局文件的根目录。
答案 1 :(得分:90)
我有一个固定大小的DialogFragment,在XML主布局中定义了以下内容(在我的例子中是LinearLayout):
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="1000dp"
android:minHeight="450dp"
答案 2 :(得分:50)
在我的案例中唯一有用的是这里提出的解决方案: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
}
答案 3 :(得分:41)
控制DialogFragment
宽度和高度的一种方法是确保其对话框尊重您的视图的宽度和高度,如果它们的值为WRAP_CONTENT
。
ThemeOverlay.AppCompat.Dialog
实现此目的的一种简单方法是使用Android支持库中包含的ThemeOverlay.AppCompat.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
与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();
}
您还可以在创建对话框时将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
与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
与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();
}
在较旧的Android API上,Dialog
似乎有一些宽度问题,因为它们的标题(即使您没有设置)。
如果您不想使用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;
}
我试图让对话框尊重布局的宽度和高度,而不是以编程方式指定固定大小。
我认为android:windowMinWidthMinor
和android: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>
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new Dialog(getActivity(), R.style.Theme_Material_Light_Dialog_NoMinWidth);
}
解决方案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());
}
解决方案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();
}
答案 4 :(得分:29)
DialogFragment
布局真的麻木了。
创建DialogFragment
时,您可以选择覆盖onCreateView
(通过ViewGroup
将.xml布局附加到)或onCreateDialog
,而不是OnCreateDialog
。
你不能覆盖这两种方法,因为你很可能会混淆Android 至于何时或是否你的对话框布局被夸大了! WTF?
是否覆盖OnCreateView
或OnCreateDialog
的选择取决于您打算如何使用对话框。
OnCreateView
。onCreateDialog
。这可能是世界上最糟糕的事情。
onCreateDialog
精神错乱因此,您在DialogFragment
中覆盖AlertDialog
来创建onCreateDialog
的自定义实例以在窗口中显示。凉。但请记住,ViewGroup
未收到null
以将自定义.xml布局附加到。没问题,您只需将inflate
传递给onCreateDialog
方法。
让疯狂开始。
当您覆盖background_color
,Android 完全忽略您膨胀的.xml布局的根节点的几个属性时。这包括但不限于:
layout_gravity
layout_width
layout_height
layout_width
这几乎是滑稽的,因为您需要设置每个.xml布局的
layout_height
和DialogFragment
,否则Android Studio会为您带来一个漂亮的红色羞耻徽章。
只是字 background_color
让我想要呕吐。我可以写一本充满Android陷阱和snafus的小说,但这个是最内心的一个。
为了恢复理智,首先,我们声明一种样式来恢复我们期望的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
上面的样式继承自Dialogs的基本主题(在本例中的AlertDialog
主题中)。
接下来,我们以编程方式应用样式,将Android放弃的值放回原处并恢复标准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
再次看起来像layout_width
。也许这还不错。
如果您希望layout_height
AlertDialog
或layout_width
为layout_height
设置显示(非常可能) ,然后猜猜你还没完成!
如果你意识到如果你试图在你的新风格中设置一个特定的<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
,那么欢闹就会继续,Android也会完全忽略它!:
@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);
}
要设置SPECIFIC窗口的宽度或高度,您可以使用整个“nuther”方法并处理WindowManager.LayoutParams
:
ViewGroup.LayoutParams
许多人都遵循Android将
ViewGroup.LayoutParams
投射到更一般的WindowManager.LayoutParams
的错误示例,只是向右转并将LayoutParams
投回到DialogFragment
几行之后。有效的Java被诅咒,除了使代码更难破译之外,不必要的铸造提供了许多东西。附注:Android SDK中有一些
onCreateDialog
的重复次数 - 这是设计极其糟糕的完美示例。
覆盖AlertDialog
的{{1}}:
background_color
外观,请创建一个设置transparent
= layout_gravity
和center
= onCreateDialog
的样式,并将该样式应用于{ {1}}。layout_width
和/或layout_height
,请使用onResume
LayoutParams
中以编程方式执行此操作
答案 5 :(得分:12)
当我需要使DialogFragment更宽一点时我设置minWidth:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="320dp"
... />
答案 6 :(得分: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>
答案 7 :(得分:5)
我修复了它设置根元素布局参数。
int width = activity.getResources().getDisplayMetrics().widthPixels;
int height = activity.getResources().getDisplayMetrics().heightPixels;
content.setLayoutParams(new LinearLayout.LayoutParams(width, height));
答案 8 :(得分: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">
.....
答案 9 :(得分:4)
就我而言,DialogFragment
像Fragment
一样占据了全部活动规模。 DialogFragment
基于XML布局,而不是AlertDialog
。我的错误是将对话框片段作为常规片段添加到FragmentManager
:
fragmentManager?.beginTransaction()?.run {
replace(R.id.container, MyDialogFragment.newInstance(), MyDialogFragment.TAG)
addToBackStack(MyDialogFragment.TAG)
}?.commitAllowingStateLoss()
相反,我需要show
对话框片段:
val dialogFragment = MyDialogFragment.newInstance()
fragmentManager?.let { dialogFragment.show(it, MyDialogFragment.TAG) }
进行一些编辑后(我的布局中有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
}
现在,它已定义宽度和高度,而不是完整的活动大小。
我想谈谈onCreateView
和onCreateDialog
。如果您有一个基于布局的对话框片段,则可以使用这两种方法中的任何一种。
如果使用onCreateView
,则应使用onActivityCreated
设置宽度。
如果使用onCreateDialog
而不是onCreateView
,则可以在那里设置参数。不需要onActivityCreated
。
onCreateDialog(savedInstanceState:Bundle?)的替代乐趣:对话框{ 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
}
答案 10 :(得分:3)
您可以使用百分比作为宽度。
<style name="Theme.Holo.Dialog.MinWidth">
<item name="android:windowMinWidthMajor">70%</item>
我在这个例子中使用了Holo Theme。
答案 11 :(得分:3)
您可以在下面的代码中设置java的布局宽度和高度。
final AlertDialog alertDialog = alertDialogBuilder.create();
final WindowManager.LayoutParams WMLP = alertDialog.getWindow().getAttributes();
WMLP.gravity = Gravity.TOP;
WMLP.y = mActionBarHeight;
WMLP.x = getResources().getDimensionPixelSize(R.dimen.unknown_image_width);
alertDialog.getWindow().setAttributes(WMLP);
alertDialog.show();
答案 12 :(得分:2)
这是科特林版本
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
}
答案 13 :(得分:2)
我没有令人信服的理由覆盖onResume
的{{1}}中的onStart
或Window
来设置DialogFragment
的宽度和高度-这些特殊的生命周期方法可能会被重复调用,并且由于诸如多窗口切换,后台应用程序前台和前台应用程序等等之类的事情而导致不必要地多次执行该调整大小的代码。重复的结果相当琐碎,但是为什么要解决呢?
在覆盖的Dialog
方法中设置宽度/高度而不是设置将是一项改进,因为该方法实际上每个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);
}
,而与设备方向无关。如果您希望横向对话框的宽度不那么宽,则可以事先检查是否match_parent
。
答案 14 :(得分:2)
我使用AlertDialog.Builder创建对话框,所以我在OnShowListener中使用了Rodrigo的答案。
dialog.setOnShowListener(new OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);
dialog.getWindow().setLayout((int)(312 * outMetrics.density), (int)(436 * outMetrics.density));
}
});
答案 15 :(得分:1)
将自定义对话框布局的父布局设置为 RelativeLayout ,自动获取常用的宽度和高度。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
答案 16 :(得分:1)
我找到的最佳解决方案是覆盖onCreateDialog()
而不是onCreateView()
。 setContentView()将在充气前设置正确的窗口尺寸。它消除了在资源文件中存储/设置尺寸,背景颜色,样式等并手动设置它们的需要。
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(getActivity());
dialog.setContentView(R.layout.fragment_dialog);
Button button = (Button) dialog.findViewById(R.id.dialog_button);
// ...
return dialog;
}
答案 17 :(得分:1)
简单明了:
@Override
public void onResume() {
// Sets the height and the width of the DialogFragment
int width = ConstraintLayout.LayoutParams.MATCH_PARENT;
int height = ConstraintLayout.LayoutParams.MATCH_PARENT;
getDialog().getWindow().setLayout(width, height);
super.onResume();
}
答案 18 :(得分:1)
在我的情况下,它是由align_parentBottom="true"
内部视图的RelativeLayout
引起的。删除了所有的alignParentBottom并将所有布局更改为垂直LinearLayouts并且问题消失了。
答案 19 :(得分:0)
其他答案都不适合我。我只需要创建样式就可以解决这个问题,您可以在其中选择屏幕的百分比,您希望对话采用:
<style name="RelativeDialog" parent="android:style/Theme.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="windowFixedWidthMajor">90%</item>
<item name="windowFixedWidthMinor">90%</item>
<item name="android:windowMinWidthMajor">90%</item>
<item name="android:windowMinWidthMinor">90%</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
</style>
不仅仅是将此样式设置为对话框,例如:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.RelativeDialog)
}
答案 20 :(得分:0)
使用 RelativeLayout 作为 DialogFragment
的父级答案 21 :(得分:0)
早期的解决方案之一几乎起作用。我尝试了一些稍微不同的东西,它最终为我工作。
(确保你看看他的解决方案) 这是他的解决方案.. Click Here 它的工作原理除外:builder.getContext()。getTheme()。applyStyle(R.style.Theme_Window_NoMinWidth,true);
我把它改成了
@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);
最后一行真的不同。
答案 22 :(得分:0)
这将很好地工作。
@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);
}
答案 23 :(得分:0)
添加到您的FragmentDialog
:
public void onResume() {
Window window = getDialog().getWindow();
Point size = new Point();
Display display = window.getWindowManager().getDefaultDisplay();
display.getSize(size);
window.setLayout( (int)(size.x * 0.9), WindowManager.LayoutParams.WRAP_CONTENT );
window.setGravity( Gravity.CENTER );
super.onResume();
}
答案 24 :(得分:0)
@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);
}
}
答案 25 :(得分:-4)
要获得几乎覆盖整个scree的Dialog:首先定义一个ScreenParameter类
public class ScreenParameters
{
public static int Width;
public static int Height;
public ScreenParameters()
{
LayoutParams l = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
Width= l.width;
Height = l.height;
}
}
然后你必须在getDialog.getWindow()之前调用ScreenParamater.setLayout()方法
@Override
public void onResume()
{
super.onResume();
ScreenParameters s = new ScreenParameters();
getDialog().getWindow().setLayout(s.Width , s.Height);
}