Як встановити ширину та висоту DialogFragment?


173

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

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

На жаль, я вважаю, що коли з'являється мій діалог (DialogFragment), він не відповідає layout_widthта layout_heightвказаний у своєму файлі компонування xml (і моє діалогове вікно зменшується або розширюється залежно від вмісту). Хтось знає, чи можу я отримати так, щоб моє діалогове вікно було дотримано layout_widthта layout_heightвказано у його файлі розмітки xml? На даний момент мені доведеться знову вказати ширину та висоту діалогового вікна в методі свого DialogFragment onResume()таким чином:

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

... І таким чином, небажано, потрібно пам’ятати, щоб в будь-якому майбутньому змінити ширину та висоту діалогу в двох місцях.


2
Подумайте про прийняття відповіді jpmcosta. Це не хак, і це фактично виправляє проблему.
Богдан Зурак

Відповіді:


168

Якщо ви перетворюєте безпосередньо з значень ресурсів:

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). Він не є ідеальним, але, принаймні, працює для того, щоб мати відносну макет як корінь файлу макета діалогу.


3
У моєму випадку ця відповідь не працює (для DialogFragment). Мені довелося використовувати параметри FragmentLayout для зміни розміру вікна, що відображається.
Rusfearuth

3
Мені довелося загорнути свою верстку, RelativeLayoutі це мені допомогло. Велике спасибі за рішення - це врятувало мені багато часу.
Джонні Доу

62
Це чудово працює для мене (Android 4.0+), як тільки я зрозумів, що це має бути onResume(), а не onCreateView(). (Мій кореневий макет - це відносна макет, загорнутий у ScrollView.)
Jonik,

14
Корисно в деяких випадках: використовувати всю ширину екрана:int width = getResources().getDisplayMetrics().widthPixels
Jonik

6
+1 для Jonik. -1 для Річарда. Я завжди використовую фрагменти підтримки і ніколи не вмів змусити це працювати onCreateDialog(). Потрібно бути в onResume().
MinceMan

146

Я закінчив переосмислення 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);
}

2
Дякую ! Це працює для мене! Крім того, це елегантний спосіб зробити це.
AntoineP

1
@jmaculate - Швидке запитання: коли ти робиш кастинг (android.view.WindowManager.LayoutParams), з чого ти це робиш ? Я був спантеличений при виборі правильного імпорту для LayoutParamsпояви в перших трьох рядках функції. Закінчився вибір (android.view.WindowManager.LayoutParams). Це має бути правильним?
Dev-iL

@ Dev-iL getAttributes () повертає WindowManger.LayoutParams, але в моєму випадку я неявно передав це ViewGroup.LayoutParams, тому що це все, що мені потрібно (Ефективна Java, пункт 52) - я відредагую питання, щоб це відобразити
jmaculate

1
Якщо вам потрібно це зробити ще раз android.view.WindowManager.LayoutParams, не потрібно використовувати ViewGroup.LayoutParamsтри рядки вище ... Тут ви не отримуєте жодної гнучкості. Як би там не було, дякую за цю добру відповідь!
Кевін Робатель

2
Це найкраще рішення. Ви навіть можете використовувати певне значення пікселів разом із MATCH_PARENT або WRAP_CONTENT.
Коеш

98

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

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

4
Я виявив, що мені потрібні середня ширина і мінімальна висота в соті - але не в ICS.
daveywc

1
Здається, це працює на перший погляд, але цього, мабуть, слід уникати. Перегляд буде продовжуватися поза екраном залежно від ширини пристрою, тому якщо у вас є кнопки в правому нижньому куті, вони не з’являться.
CodyEngel

Перегляд НЕ продовжується поза екраном. Андроїдна система, здається, гарантує, що DialogFragment залишається всередині меж перегляду (з невеликим запасом), навіть якщо ці межі менші за вказану minWidth та minHeight.
Lensflare

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
}

Ідеальне рішення і дуже добре пояснено в блозі.
varun bhardwaj

+1 getDialog().getWindow().setLayout(dialogWidth, dialogHeight); прекрасно працює для діалогового фрагмента. Але я не розумію перевірку безпеки. чому ми повинні перевіряти null?
tpk

3
@ 2943 - просто тому, що немає гарантії, що Dialog(дитина дитини DialogFragment) буде доступна в той момент, коли вона запитає. Можливо, що Android поверне нуль, коли ми зателефонуємо getDialog().
rmirabelle

@mirabelle, якщо ви припиняєте зворотний виклик onStart діалогового вікна, як діалог може бути нульовим?
rommex

49

Один із способів контролю за DialogFragmentшириною та висотою вашого продукту - переконатися, що його діалог дотримується ширини та висоти вашого перегляду, якщо їх значення WRAP_CONTENT.

Використання ThemeOverlay.AppCompat.Dialog

Один простий спосіб досягти цього - скористатися ThemeOverlay.AppCompat.Dialogстилем, включеним у бібліотеку підтримки Android.

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
Я дійсно не знаю, чому, чорт, це не прийнята відповідь. Це буквально Єдина відповідь, яка спрацьовує і не є злому (я говорю здебільшого за ваше перше рішення).
Богдан Зурак

1
на жаль, виявив це лише витративши годину на роздуми, як вирішити!
мозковий розгляд

Рішення 3 рятує моє життя. Дуже дякую
Саймон

Мені вдалося відтворити вашу проблему на старих API Android. Додано кілька альтернатив, які можуть вам допомогти.
jpmcosta

Рішення 1 працювало на мене. я просто використовувався Theme.MaterialComponents.Light.Dialogяк батьківський і використовував цей стиль у конструкторі MaterialAlertDialogBuilder. Натрапили на вашу відповідь через 1 годину дослідження. Спасибі і великі пальці вгору.
Шейція уль Хассан

39

Gotcha № 13: DialogFragmentМакети

Це справді думка оніміння.

Створюючи a DialogFragment, ви можете вибрати переосмислення onCreateView(який передає a, ViewGroupщоб прикріпити ваш .xml макет) або onCreateDialog, що ні.

Ви не повинні перекривати обидва способи, тому що ви, швидше за все, заплутаєте Android щодо того, коли або якщо макет вашого діалогового вікна був завищений! WTF?

Вибір того, чи слід перекривати OnCreateDialogчи OnCreateViewзалежати від того, як ви плануєте використовувати діалогове вікно.

  • Якщо ви запустите діалогове вікно у вікні (нормальна поведінка), очікується, що ви перекриєте OnCreateDialog.
  • Якщо ви маєте намір вставити фрагмент діалогу в існуючий макет інтерфейсу (FAR рідше), то очікується, що ви зможете переопрацювати OnCreateView.

Це, можливо, найгірше в світі.

onCreateDialog Божевілля

Таким чином, ви переосмислюєте onCreateDialogсвоє DialogFragmentстворення, щоб створити індивідуальний екземпляр AlertDialogвідображення у вікні. Класно. Але пам'ятайте, що onCreateDialogне отримує , ViewGroupщоб прикріпити призначені для користувача XML - макет до . Без проблем, ви просто переходите nullдо inflateметоду.

Нехай розпочнеться божевілля.

Коли ви переосмислюєте onCreateDialog, Android ПОСЛУГО ЗАПАСНУЄ декілька атрибутів кореневого вузла макета .xml, який ви надуваєте. Це включає, але, ймовірно, не обмежується:

  • background_color
  • layout_gravity
  • layout_width
  • layout_height

Це майже комічно, тому що вам потрібно встановити layout_widthі layout_heightВСЕ. .Xml макет або 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знову. Можливо, це досить добре.

Але зачекай, є ще більше!

Якщо ви хочете встановити 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>

Щоб встановити СПЕЦІФІЧНУ ширину або висоту вікна, ви повинні перейти до цілого методу "нуттер" і мати справу з 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, що непотрібне лиття не пропонує нічого, крім того, щоб зробити код ще складніше розшифрувати.

Побічна примітка: Є двадцять повторень LayoutParamsдля Android SDK - прекрасний приклад радикально поганого дизайну.

Підсумок

Для DialogFragments, що перевизначає onCreateDialog:

  • Щоб відновити стандартний AlertDialogзовнішній вигляд, створіть стиль, який задає background_color= transparentі layout_gravity=, centerі застосуйте цей стиль у onCreateDialog.
  • Щоб встановити конкретний layout_widthта / або layout_height, виконайте це програмно onResumeразом ізLayoutParams
  • Щоб зберегти розум, намагайтеся не думати про Android SDK.

13
Читання цієї відповіді змушує мене плакати.
Басинатор

3
Чувак, ти описав саме те, що я зараз переживаю.
Мерт Гюлсой

2
Android - це лайно. Я відчуваю, ти брате. потрібен контекст для всього, процес додатків вбиває, відсутність бібліотеки підтримки для деяких речей, список продовжується
DennisVA

1
@rmirabelle - ця відповідь насправді допомагає, ви можете насправді написати середній блог, і може бути корисною для багатьох. У моєму випадку я використовую макет обмежень та DialogFragment, тому з Android було ігноровано в Android 9, нижче Android 9 він працює добре. Я додав - "android: windowMinWidthMajor", android: windowMinWidthMinor "у стилі, і він почав працювати нормально.
Rahul


14

Коли мені потрібно зробити DialogFragment трохи ширшим, я встановлюю minWidth:

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

1
Найкраще рішення на мій погляд!
Фабіан Кнапп

що робити, якщо ти хочеш зробити це вужчим?
Даніель

8

Я не бачу підстав , щоб скасувати onResumeабо onStartвстановити ширину і висоту в Windowмежах DialogFragment«s 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незалежно від орієнтації пристрою. Якщо ви хочете, щоб діалогове вікно не було таким широким, ви можете 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>


5

Я зафіксував це, встановивши параметри компонування кореневих елементів.

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

5

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

      .....

Я спробую це спробувати, тому що якщо це працює послідовно, це VASTLY-підхід до кодування частини макета в XML та частини в коді. Спасибі
rmirabelle

Мені подобається ідея такого підходу, але при тестуванні він дає інший макет, ніж просто зміна висоти та ширини програмно. Наприклад, загальна ширина насильно зменшується до максимальної ширини, яку надає AlertDialog (імовірно, через стилі Android). Коли я просто встановлюю ш і ч за допомогою коду, стиль AlertDialog буде відмінено. Однак це може відповідати багатьом потребам і є чудовою ідеєю. Хай живе найгірший SDK в історії.
rmirabelle

Працював чудово для onCreateView, поки я не захотів змінити внутрішню ширину на match_parent ...
tudor

5

Ось котлін версія

    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
    }

4

Можна використовувати відсоток для ширини.

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

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


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

2

Я створюю діалог за допомогою 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));
            }

        });

(В основному для майбутніх читачів :) Дивіться коментар Snicolasу дискусії " DialogFragmentпроти AlertDialog" в stackoverflow.com/a/7979823/3372061 .
Dev-iL

2

Працюючи на Android 6.0, зіткнувся з тією ж проблемою. AlertDialogза замовчуванням widthвстановлено попередньо визначений набір у темі незалежно від фактичного widthнабору в корені користувацького перегляду Layout. Я був в змозі отримати його , щоб встановити належним чином регулюючи widthз loading_message TextView. Без подальшого дослідження, здається, що розмір фактичних елементів та обробка кореня 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>

2

Легкий і міцний:

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

2

У моєму випадку 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
}

Тепер він визначив ширину та висоту, а не повний розмір активності.

Я хочу сказати про onCreateViewі onCreateDialog. Якщо у вас є фрагмент діалогу, заснований на макеті, ви можете використовувати будь-який із цих двох методів.

1) Якщо ви використовуєте onCreateView, то вам слід використовувати onActivityCreatedдля встановлення ширини.

2) Якщо ви використовуєте onCreateDialogзамість onCreateView, ви можете встановити там параметри. onActivityCreatedне знадобиться.

override fun 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
}

Ви зберегли мій день, встановивши ширину в onActivityCreate працював на мене.
Агар Мідді

@ManishKumarSharma, удачі!
CoolMind

1

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


1

Встановіть для батьківського макета користувальницького діалогу діапазон значення " Відносний макет" , автоматично отримуйте загальну ширину та висоту.

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

Це працювало для мене. Я хотів використовувати ConstraintLayout, щоб викласти елементи керування в діалоговому вікні, тому я використав RelativeLayout для кореневого макета, а потім поставив ConstraintLayout безпосередньо всередині нього. Це дало мені діалог нормального розміру. Коли я поставив ConstraintLayout як корінь, не змінюючи нічого іншого, то ширина діалогу вбудована до не дуже широкої!
leafcutter

1

Одне з попередніх рішень майже спрацювало. Я спробував щось трохи інше, і це в мене закінчилося.

(Обов’язково подивіться на його рішення) Це було його рішення .. Клацніть тут Це працювало, крім: 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);

Останній рядок - що насправді відрізняється.


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

0

Це найпростіше рішення

Найкраще рішення, яке я знайшов - замінити 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;
}

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

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

Це майже те, про що йдеться у прийнятій відповіді від 3+ років тому.
Аділ Хуссейн

-4

Щоб отримати діалогове вікно, яке охоплює майже весь екран: Спершу визначте клас 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);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.