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

173

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

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). Он не идеален, но, по крайней мере, работает с RelativeLayout в качестве корня файла макета вашего диалога.

Blix247
источник
3
Этот ответ не работает в моем случае (для DialogFragment). Мне пришлось использовать параметры FragmentLayout для изменения размера окна показа.
Rusfearuth
3
Я должен был обернуть мой макет, RelativeLayoutи это помогло мне. Большое спасибо за решение - оно сэкономило мне много времени.
Джонни Доу
62
Это прекрасно работает для меня (Android 4.0+), как только я понял, что это должно быть onResume(), а не onCreateView(). (Мой корневой макет - RelativeLayout, обернутый в ScrollView.)
Jonik
14
Полезно в некоторых случаях: использовать всю ширину экрана:int width = getResources().getDisplayMetrics().widthPixels
Jonik
6
+1 для Джоника. -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);
}
jmaculate
источник
2
Спасибо ! Меня устраивает ! Более того, это элегантный способ сделать это.
AntoineP
1
@jmaculate - Быстрый вопрос: когда вы читаете, откуда вы (android.view.WindowManager.LayoutParams)это делаете? Я был озадачен, выбирая правильный импорт для LayoutParamsпоявления в первых 3 строках функции. Закончился выбор (android.view.WindowManager.LayoutParams). Это должно быть правильно?
Dev-IL
@ Dev-iL getAttributes () возвращает WindowManger.LayoutParams, но в моем случае я неявно приводил его к ViewGroup.LayoutParams, потому что это все, что мне нужно (Effective Java, Item 52) - я отредактирую вопрос, чтобы отразить это
jmaculate
1
Если вам нужно привести его снова android.view.WindowManager.LayoutParams, бесполезно использовать ViewGroup.LayoutParamsтри строки выше ... Вы здесь не получаете никакой гибкости. Как бы то ни было, спасибо за хороший ответ!
Кевин Робатель
2
Это лучшее решение. Вы даже можете использовать определенное значение пикселей вместе с MATCH_PARENT или WRAP_CONTENT.
Коеш
98

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

android:layout_width="match_parent"
android:layout_height="match_parent"
android:minWidth="1000dp"
android:minHeight="450dp"
Jose_GD
источник
4
Я обнаружил, что мне нужны midWidth и minHeight в сотах, но не в ICS.
daveywc
1
На первый взгляд это работает, но, вероятно, этого следует избегать. Вид будет продолжаться вне экрана в зависимости от ширины устройства, поэтому, если у вас есть кнопки в правом нижнем углу, они не будут отображаться.
CodyEngel
Просмотр не продолжается за пределами экрана. Система Android, кажется, гарантирует, что 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
}
Родриго
источник
Идеальное решение и очень хорошо объяснено в блоге.
Варун Бхардвай
+1 getDialog().getWindow().setLayout(dialogWidth, dialogHeight); отлично работает для DialogFragment. Но я не понимаю проверки безопасности. почему мы должны проверить null?
TPK
3
@ 2943 - просто потому, что нет никакой гарантии, что Dialog(ребенок DialogFragment) будет доступен в момент запроса. Вполне возможно, что Android вернет ноль, когда мы позвоним getDialog().
rmirabelle
@mirabelle, если вы используете функцию обратного вызова onStart для диалога, как диалог может быть нулевым?
Роммекс
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();
}
jpmcosta
источник
4
Я действительно не знаю, какого черта это не принятый ответ. Это буквально единственный ответ, который работает и не является взломом (я говорю в основном о вашем первом решении).
Богдан Зурак
1
к сожалению нашел это только после того как потратил час придумывая как решить!
Brainvision
Решение 3 спасает мою жизнь. Большое спасибо
Симон
Я смог воспроизвести вашу проблему на старых Android API. Добавлены некоторые альтернативы, которые могут вам помочь.
Jpmcosta
Решение 1 сработало для меня. я просто использовал в Theme.MaterialComponents.Light.Dialogкачестве родителя и использовал этот стиль в конструкторе MaterialAlertDialogBuilder. Наткнулся на ваш ответ после исследования 1 часа. Спасибо и палец вверх.
Shahood уль Хасан
39

Получил # 13: DialogFragmentмакеты

Это своего рода оцепенение на самом деле.

При создании DialogFragment, вы можете выбрать переопределить onCreateView(который передает, ViewGroupчтобы присоединить ваш XML-макет) или onCreateDialog, что нет.

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

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

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

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

onCreateDialog невменяемость

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

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

При переопределении onCreateDialogAndroid полностью игнорирует несколько атрибутов корневого узла разметки .xml, которую вы раздувает. Это включает, но, вероятно, не ограничивается:

  • background_color
  • layout_gravity
  • layout_width
  • layout_height

Это почти комично, так как вы должны установить layout_widthи layout_heightдля каждого .xml Layout, или Android Studio даст вам приятный маленький красный значок позора.

Просто слово DialogFragment заставляет меня хотеть рвать. Я мог бы написать роман, наполненный Android getchas и snafus, но этот - один из самых внутренних.

Чтобы вернуться к здравомыслию, сначала мы объявляем стиль для восстановления ПРОСТО 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 - прекрасный пример радикально плохого дизайна.

В итоге

Для DialogFragmentпереопределения onCreateDialog:

  • Чтобы восстановить стандартный AlertDialogвнешний вид, создайте стиль, который устанавливает background_color= transparentи layout_gravity=, centerи примените этот стиль в onCreateDialog.
  • Чтобы установить конкретный layout_widthи / или layout_height, сделать это программно onResumeсLayoutParams
  • Чтобы сохранить здравомыслие, постарайтесь не думать об Android SDK.
rmirabelle
источник
13
Чтение этого ответа заставляет меня плакать.
Басинатор
3
Чувак, ты описал именно то, что я испытываю сейчас.
Мерт Гюльсой,
2
Андроид это дерьмо. Я чувствую тебя, братан. нужен контекст для всего, убивает процесс приложения, нехватка библиотек поддержки для некоторых вещей, список можно
продолжить
1
@rmirabelle - этот ответ действительно помогает, вы можете написать средний блог и может быть полезным для многих. В моем случае я использую макет ограничений и DialogFragment, поэтому в Android 9 игнорировался, ниже Android 9 работает нормально. Я добавил - "android: windowMinWidthMajor", android: windowMinWidthMinor "в стиле, и он начал работать нормально.
Rahul
@Rahul medium.com/@rmirabelle/...
rmirabelle
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- именно эти методы жизненного цикла могут вызываться неоднократно и без необходимости выполнять , что изменение размера кода более чем один раз из - за таких вещей , как мульти переключения окон, фоновый затем приоритетное приложение и так далее. Последствия этого повторения довольно тривиальны, но зачем соглашаться на это?

Установка width / height вместо этого внутри переопределенного 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заранее.

N1hk
источник
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. Просто оберните вашу 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">

      .....
NameSpace
источник
Я собираюсь дать этому попытку, потому что, если он работает согласованно, это ДЕЙСТВИТЕЛЬНО превосходный подход к кодированию части макета в XML и части в коде. Спасибо
rmirabelle
Мне нравится идея этого подхода, но при тестировании он дает другой макет, чем простое изменение высоты и ширины программно. Например, общая ширина принудительно уменьшается до максимальной ширины, предоставляемой AlertDialog (предположительно из-за стилей Android). Когда я просто устанавливаю w и h с помощью кода, стиль 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 Theme для этого примера.

StefanoM5
источник
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в обсуждении " DialogFragmentvs 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>
C0D3LIC1OU5
источник
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
}
CoolMind
источник
Вы сохранили мой день, настройка ширины в onActivityCreated у меня сработала.
Агарь Магди
@ManishKumarSharma, удачи!
CoolMind
1

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

mehmet6parmak
источник
1

Установите для родительского макета пользовательского диалогового окна значение RelativeLayout , автоматически получайте общую ширину и высоту.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
vishnuc156
источник
Это сработало для меня. Я хотел использовать 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);

Последняя строка действительно отличается.

TheAppFoundry
источник
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;
}
parkgrrr
источник
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();
}
RonTLV
источник
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);
}
Toye_Brainz
источник