Как установить ширину и высоту DialogFragment?

Я указываю макет моего DialogFragment в файле макета xml (назовем его layout_mydialogfragment.xml ) и его layout_width и layout_height частности (каждый будет 100dp , скажем так). Затем я раздуваю этот макет в моем методе onCreateView(...) следующим образом:

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

К сожалению, я обнаружил, что, когда появляется мой диалог (DialogFragment), он не layout_width и layout_height указанные в его файле макета xml (и мой диалог сжимается или расширяется в зависимости от содержимого). Кто-нибудь знает, может ли или как я могу получить мой диалог, чтобы уважать layout_width и layout_height указанные в его файле макета xml? В настоящий момент мне нужно снова указать ширину и высоту моего диалога в моем методе onResume() в onResume() следующим образом …

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

… И, следовательно, нежелательно, помните, чтобы вносить любые изменения в ширину и высоту диалога в двух местах.

Solutions Collecting From Web of "Как установить ширину и высоту DialogFragment?"

Если вы конвертируете непосредственно из значений ресурсов:

 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 был корневым файлом макета вашего диалогового окна.

Я получил фиксированный размер DialogFragment, определяющий следующее в главном макете XML (LinearLayout в моем случае):

 android:layout_width="match_parent" android:layout_height="match_parent" android:minWidth="1000dp" android:minHeight="450dp" 

Я закончил переопределять Fragment.onResume() и захватил атрибуты из базового диалога, а затем задал параметры width / height. Я установил match_parent высоту / ширину match_parent в match_parent . Обратите внимание, что этот код, похоже, уважает поля, определенные мной в макете xml.

 @Override public void 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); super.onResume(); } 

Единственное, что сработало в моем случае, – это решение, указанное здесь: 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 } 

Я пытался сделать диалог уважением к ширине и высоте моего макета, не указав фиксированный размер программно.

Я понял, что 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(); } 

Когда мне нужно сделать DialogFragment немного шире, я устанавливаю minWidth:

 <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:minWidth="320dp" ... /> 

Gotcha # 13: Макеты DialogFragment

На самом деле это отвращение.

При создании DialogFragment вы можете переопределить onCreateView (который передает ViewGroup для прикрепления вашего макета .xml) или onCreateDialog , а это не так.

Вы не должны переопределять оба метода tho, потому что вы, скорее всего, будете путать Android с тем, когда или когда макет вашего диалога был завышен! WTF?

Выбор того, следует ли переопределять OnCreateDialog или OnCreateView зависит от того, как вы собираетесь использовать диалог.

  • Если вы запустите диалог в окне (нормальное поведение), вы должны переопределить OnCreateDialog .
  • Если вы намерены встраивать фрагмент диалога в существующий макет интерфейса (FAR менее распространенный), тогда вы должны переопределить OnCreateView .

Это, возможно, самое худшее в мире.

onCreateDialog Insanity

Таким образом, вы переопределяете onCreateDialog в своем DialogFragment чтобы создать индивидуальный экземпляр AlertDialog для отображения в окне. Круто. Но помните, onCreateDialog получает ViewGroup чтобы ViewGroup свой собственный .xml макет. Нет проблем, вы просто передаете значение null методу inflate .

Пусть начнется безумие.

Когда вы переопределяете onCreateDialog , Android ПОЛНОСТЬЮ ИГРАЕТ несколько атрибутов корневого узла .xml Layout, который вы раздуваете. Это включает, но, возможно, не ограничивается:

  • background_color
  • layout_gravity
  • layout_width
  • layout_height

Это почти комично, так как вам нужно установить layout_width и layout_height из КАЖДОГО .xml Layout или 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> 

Вышеупомянутый стиль наследуется от базовой темы для Dialogs (в примере AppCompat в этом примере).

Затем мы применяем стиль программно, чтобы вернуть значения, которые Android просто отбросил, и восстановить стандартный AlertDialog вид 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 . Возможно, это достаточно хорошо.

Но подождите, есть еще!

Если вы хотите установить SPECIFIC layout_width или layout_height для своего AlertDialog когда он показан (очень вероятно), тогда угадайте, что вы еще не сделали!

Веселье продолжается, так как вы понимаете, что если вы попытаетесь установить конкретную 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> 

Чтобы установить ширину или высоту окна 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); } 

Многие люди следят за плохим примером Android, ViewGroup.LayoutParams от WindowManager.LayoutParams до более общей ViewGroup.LayoutParams , только чтобы повернуть направо и бросить ViewGroup.LayoutParams обратно в WindowManager.LayoutParams несколько строк позже. Эффективная Java будет проклята, что ненужное кастинг предлагает НИЧЕГО, кроме того, что код еще сложнее расшифровать.

Замечание: Есть несколько LayoutParams повторений LayoutParams через Android SDK – прекрасный пример радикально плохого дизайна.

В итоге

Для DialogFragment s, которые переопределяют onCreateDialog :

  • Чтобы восстановить стандартный AlertDialog вид AlertDialog , создайте стиль, который устанавливает background_color = transparent и layout_gravity = center и применяет этот стиль в onCreateDialog .
  • Чтобы установить конкретную layout_width и / или layout_height , сделайте это программно в onResume с LayoutParams
  • Чтобы поддерживать здравомыслие, постарайтесь не думать об Android SDK.

Я установил его, установив параметры компоновки корневого элемента.

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

Вот способ установить ширину / высоту DialogFragment в xml. Просто заверните свою иерархию view в 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"> ..... 

Измерение в самом внешнем макете не работает в диалоговом окне. Вы можете добавить макет, где заданный размер ниже самого внешнего.

 <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> 

Я создаю диалог, используя AlertDialog.Builder, поэтому я использовал ответ Родриго внутри OnShowListener.

 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)); } }); 

В моем случае это было вызвано align_parentBottom="true" данный для представления внутри RelativeLayout . Удалили все alignParentBottom и изменили все макеты на вертикальные LinearLayouts и проблема исчезла.

Работа над Android 6.0 столкнулась с той же проблемой. AlertDialog будет по умолчанию предустановленной width заданной в теме, независимо от фактической width установленной в корневом Layout пользовательского вида. Я смог заставить его правильно настроить width loading_message . Не исследуя далее, кажется, что определение размеров фактических элементов и обтекание корневого Layout вокруг них заставляет его работать должным образом. Ниже представлен XML-макет диалогового окна загрузки, которое правильно устанавливает width диалогового окна. Использование этой библиотеки для анимации.

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/custom_color" android:padding="@dimen/custom_dimen"> <com.github.rahatarmanahmed.cpv.CircularProgressView xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/progress_view" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerHorizontal="true" app:cpv_color="@color/white" app:cpv_animAutostart="true" app:cpv_indeterminate="true" /> <TextView android:id="@+id/loading_message" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_below="@+id/progress_view" android:layout_centerHorizontal="true" android:gravity="center" android:textSize="18dp" android:layout_marginTop="@dimen/custom_dimen" android:textColor="@color/white" android:text="@string/custom_string"/> </RelativeLayout> 

Вы можете под кодом установить ширину и высоту макета из 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(); 

Вы можете использовать процент для ширины.

 <style name="Theme.Holo.Dialog.MinWidth"> <item name="android:windowMinWidthMajor">70%</item> 

Я использовал тему Holo для этого примера.

Установите Parent Layout Layout Layout, чтобы получить общую ширину и высоту автоматически.

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

Одно из ранних решений почти сработало. Я попробовал что-то немного другое, и это закончилось тем, что работало на меня.

(Удостоверьтесь, что вы смотрите на его решение) Это было его решение .. Нажмите здесь Это сработало, за исключением: 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); 

Последняя строка на самом деле отличается.

 @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); } } 

Чтобы получить диалоговое окно, которое охватывает почти весь экран: Сначала определите класс 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; } } 

Затем вы должны вызвать ScreenParamater перед вашим методом getDialog.getWindow (). SetLayout ()

 @Override public void onResume() { super.onResume(); ScreenParameters s = new ScreenParameters(); getDialog().getWindow().setLayout(s.Width , s.Height); }