Jak ustawić szerokość i wysokość DialogFragment?


173

Określam układ mojego DialogFragment w pliku układu xml (nazwijmy go layout_mydialogfragment.xml), a szczególnie jego atrybuty layout_widthi layout_height( 100dppowiedzmy każdy). Następnie zawyżam ten układ w metodzie DialogFragment w onCreateView(...)następujący sposób:

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

Niestety stwierdzam, że kiedy pojawia się moje okno dialogowe (DialogFragment), nie jest ono zgodne z layout_widthi layout_heightokreślone w jego pliku układu xml (a moje okno dialogowe zmniejsza się lub rozszerza w zależności od zawartości). Czy ktoś wie, czy lub jak mogę sprawić, by moje okno dialogowe przestrzegało layout_widthi layout_heightokreślone w pliku układu XML? W tej chwili muszę ponownie określić szerokość i wysokość mojego okna dialogowego w metodzie mojego DialogFragment w onResume()następujący sposób ...

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

... A zatem, niechcący, należy pamiętać o przyszłych zmianach szerokości i wysokości okna dialogowego w dwóch miejscach.


2
Rozważ przyjęcie odpowiedzi jpmcosta. To nie jest hack i faktycznie rozwiązuje problem.
Bogdan Zurac

Odpowiedzi:


168

Jeśli konwertujesz bezpośrednio z wartości zasobów:

int width = getResources().getDimensionPixelSize(R.dimen.popup_width);
int height = getResources().getDimensionPixelSize(R.dimen.popup_height);        
getDialog().getWindow().setLayout(width, height);

Następnie określ match_parent w swoim układzie okna dialogowego:

android:layout_width="match_parent"
android:layout_height="match_parent"

Musisz martwić się tylko o jedno miejsce (umieść je w swoim DialogFragment#onResume). Nie jest doskonały, ale przynajmniej działa w przypadku posiadania RelativeLayout jako katalogu głównego pliku układu twojego okna dialogowego.


3
Ta odpowiedź nie działa w moim przypadku (dla DialogFragment). Musiałem użyć parametrów FragmentLayout, aby zmienić rozmiar wyświetlanego okna.
Rusfearuth

3
Musiałem owinąć mój układ RelativeLayouti to mi pomogło. Wielkie dzięki za rozwiązanie - zaoszczędziło mi to dużo czasu.
Johnny Doe

62
To działa świetnie dla mnie (Android 4.0+), kiedy zdałem sobie sprawę, że musi być onResume(), nie onCreateView(). (Mój układ główny to RelativeLayout opakowany w ScrollView.)
Jonik,

14
Przydatne w niektórych przypadkach: użyj całej szerokości ekranu:int width = getResources().getDisplayMetrics().widthPixels
Jonik,

6
+1 dla Jonika. -1 dla Richarda. Zawsze używam fragmentów wsparcia i nigdy nie byłem w stanie tego zrobić onCreateDialog(). Musi być w środku onResume().
MinceMan,

146

Skończyło się na nadpisywaniu Fragment.onResume()i przechwytywaniu atrybutów z podstawowego okna dialogowego, a następnie ustawianiu tam parametrów szerokości / wysokości. Ustawiłem zewnętrzną wysokość / szerokość układu na match_parent. Zauważ, że ten kod wydaje się uwzględniać również marginesy, które zdefiniowałem w układzie 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
Dzięki ! Mi to pasuje ! Ponadto jest to elegancki sposób na zrobienie tego.
AntoineP,

1
@jmaculate - Szybkie pytanie: kiedy przesyłasz (android.view.WindowManager.LayoutParams), z jakiego miejsca to przesyłasz? Zaskoczyło mnie wybranie prawidłowego importu do LayoutParamspojawienia się w pierwszych 3 wierszach funkcji. Skończyło się na wyborze (android.view.WindowManager.LayoutParams). Czy to ma być poprawne?
Dev-iL

@ Dev-iL getAttributes () zwraca WindowManger.LayoutParams, ale w moim przypadku niejawnie rzutuję go na ViewGroup.LayoutParams, ponieważ to wszystko, czego potrzebuję (Efektywna Java, punkt 52)
edytuję

1
Jeśli chcesz go ponownie rzucić android.view.WindowManager.LayoutParams, nie ma sensu używać ViewGroup.LayoutParamstrzech linii powyżej ... Nie zyskujesz tutaj żadnej elastyczności. Cokolwiek, dziękuję za tę dobrą odpowiedź!
Kevin Robatel

2
To najlepsze rozwiązanie. Możesz nawet użyć określonej wartości pikseli wraz z MATCH_PARENT lub WRAP_CONTENT.
Koesh

98

Mam stały rozmiar DialogFragment definiujący następujące elementy w głównym układzie XML (w moim przypadku LinearLayout):

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

4
Okazało się, że potrzebuję midWidth i minHeight w Honeycomb - ale nie w ICS.
daveywc

1
Na pierwszy rzut oka wydaje się to działać, ale prawdopodobnie należy tego unikać. Widok będzie kontynuowany poza ekranem w zależności od szerokości urządzenia, więc jeśli masz przyciski w prawym dolnym rogu, nie pojawią się.
CodyEngel,

Widok NIE wychodzi poza ekran. Wydaje się, że system Android upewnia się, że DialogFragment pozostaje w granicach widoku (z małym marginesem), nawet jeśli te granice są mniejsze niż określone minWidth i minHeight.
Lensflare

51

Jedyne, co zadziałało w moim przypadku, to rozwiązanie wskazane tutaj: http://adilatwork.blogspot.mx/2012/11/android-dialogfragment-dialog-sizing.html

Fragment z posta na blogu 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
}

Idealne rozwiązanie i bardzo dobrze wyjaśnione na blogu.
varun bhardwaj

+1 getDialog().getWindow().setLayout(dialogWidth, dialogHeight); działa idealnie w przypadku DialogFragment. Ale nie rozumiem kontroli bezpieczeństwa. dlaczego musimy to sprawdzić null?
tpk

3
@ 2943 - po prostu dlatego, że nie ma gwarancji, że Dialog(element podrzędny DialogFragment) będzie dostępny w żądanym czasie. Możliwe, że Android zwróci wartość null, gdy zadzwonimy getDialog().
rmirabelle,

@mirabelle, jeśli korzystasz z wywołania zwrotnego onStart okna dialogowego, w jaki sposób okno dialogowe może być puste?
rommex

49

Jednym ze sposobów kontrolowania DialogFragmentszerokości i wysokości jest upewnienie się, że okno dialogowe uwzględnia szerokość i wysokość widoku, jeśli ich wartość to WRAP_CONTENT.

Za pomocą ThemeOverlay.AppCompat.Dialog

Prostym sposobem na osiągnięcie tego jest użycie ThemeOverlay.AppCompat.Dialogstylu zawartego w bibliotece obsługi systemu Android.

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

DialogFragmentz AlertDialog(zastrzeżenie:) 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();
}

Możesz także ustawić ThemeOverlay.AppCompat.Dialogjako domyślny motyw podczas tworzenia okien dialogowych, dodając go do motywu xml swojej aplikacji.
Uważaj, ponieważ wiele okien dialogowych wymaga domyślnej minimalnej szerokości, aby dobrze wyglądać.

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

DialogFragmentz Dialogwykorzystaniem 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;
}

DialogFragmentz AlertDialog, korzystając z android:alertDialogThemeor alertDialogTheme(ostrzeżenie:) 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();
}

Premia

W starszych interfejsach API systemu Android Dialogwydaje się, że mają pewne problemy z szerokością, ze względu na ich tytuł (nawet jeśli go nie ustawisz).
Jeśli nie chcesz używać ThemeOverlay.AppCompat.Dialogstylu i Dialognie potrzebujesz tytułu (lub masz niestandardowy), możesz go wyłączyć:

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

Nieaktualna odpowiedź, w większości przypadków nie zadziała

Starałem się, aby okno dialogowe uwzględniało szerokość i wysokość mojego układu, bez programowego określania stałego rozmiaru.

Doszedłem do tego android:windowMinWidthMinori android:windowMinWidthMajorspowodowałem problem. Mimo że nie były one zawarte w temacie mojego Activitylub , w jakiś sposób Dialognadal były do ​​niego stosowane Activity.

Wymyśliłem trzy możliwe rozwiązania.

Rozwiązanie 1: utwórz niestandardowy motyw okna dialogowego i użyj go podczas tworzenia okna dialogowego w 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);
}

Rozwiązanie 2: stworzenie własnego motywu być używany w ContextThemeWrapperktóre będą służyć jako Contextdla okna. Użyj tego, jeśli nie chcesz tworzyć niestandardowego motywu okna dialogowego (na przykład, gdy chcesz użyć motywu określonego przez 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());
}

Rozwiązanie 3 (z AlertDialog): wymuś android:windowMinWidthMinori android:windowMinWidthMajordo ContextThemeWrapperutworzonego przez 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
Naprawdę nie wiem, dlaczego do cholery to nie jest akceptowana odpowiedź. To dosłownie jedyna odpowiedź, która działa i nie jest hackem (mówię głównie o pierwszym rozwiązaniu).
Bogdan Zurac

1
niestety znalazłem to dopiero po spędzeniu godziny na zastanawianiu się, jak rozwiązać!
brainvision

Rozwiązanie 3 ratuje mi życie. Dziękuję bardzo
Simon

Udało mi się odtworzyć Twój problem na starszych interfejsach Android API. Dodano kilka alternatyw, które mogą ci pomóc.
jpmcosta

Rozwiązanie 1 zadziałało dla mnie. właśnie użyłem Theme.MaterialComponents.Light.Dialogjako rodzic i użyłem tego stylu w konstruktorze MaterialAlertDialogBuilder. Natknąłem się na twoją odpowiedź po 1 godzinie badań. Dzięki i kciuki w górę.
Shahood ul Hassan

39

Gotcha # 13: DialogFragmentLayouts

To naprawdę paraliżujące.

Podczas tworzenia DialogFragmentmożesz wybrać nadpisanie onCreateView(co przekazuje a, ViewGroupaby dołączyć układ .xml) lub onCreateDialog, co nie.

Nie możesz jednak nadpisywać obu metod, ponieważ najprawdopodobniej pomylisz Androida co do tego, kiedy i czy układ twojego okna dialogowego był zawyżony! WTF?

Wybór, czy nadpisać, OnCreateDialogczy OnCreateViewzależy od tego, jak zamierzasz używać okna dialogowego.

  • Jeśli otworzysz okno dialogowe w oknie (normalne zachowanie), powinieneś nadpisać OnCreateDialog.
  • Jeśli zamierzasz osadzić fragment okna dialogowego w istniejącym układzie interfejsu użytkownika (znacznie rzadziej), należy nadpisać OnCreateView.

To prawdopodobnie najgorsza rzecz na świecie.

onCreateDialog Niepoczytalność

Tak więc nadpisujesz onCreateDialogw swoim, DialogFragmentaby utworzyć niestandardową instancję AlertDialogdo wyświetlenia w oknie. Chłodny. Należy jednak pamiętać, onCreateDialogotrzyma nie ViewGroupdołączyć swój zwyczaj .xml układ do . Nie ma problemu, po prostu przechodzisz nulldo inflatemetody.

Niech rozpocznie się szaleństwo.

Podczas zastępowania system onCreateDialogAndroid CAŁKOWICIE IGNORUJE kilka atrybutów węzła głównego układu .xml, który nadmuchujesz. Obejmuje to, ale prawdopodobnie nie ogranicza się do:

  • background_color
  • layout_gravity
  • layout_width
  • layout_height

Jest to prawie komiczne, ponieważ musisz ustawić layout_widthi layout_heightKAŻDEGO .xml Layout lub Android Studio uderzy cię ładną czerwoną plakietką wstydu.

Już samo słowo DialogFragment sprawia, że ​​mam ochotę zwymiotować. Mógłbym napisać powieść pełną problemów z Androidem i snafusem, ale ta jest jedną z najbardziej ukrytych.

Aby wrócić do zdrowia psychicznego, najpierw deklarujemy styl przywracania TYLKO background_colori layout_gravityoczekujemy:

<style name="MyAlertDialog" parent="Theme.AppCompat.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:layout_gravity">center</item>
</style>

Powyższy styl dziedziczy z motywu podstawowego dla okien dialogowych (w AppCompatmotywie w tym przykładzie).

Następnie programowo stosujemy styl, aby przywrócić wartości, które Android właśnie odrzucił, i przywrócić standardowy AlertDialogwygląd i styl:

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

Powyższy kod sprawi, że będziesz AlertDialogwyglądać AlertDialogponownie. Może to wystarczy.

Ale czekaj, jest więcej!

Jeśli szukasz, aby ustawić specyficzny layout_width lub layout_heightna Twój AlertDialogkiedy to pokazane (bardzo prawdopodobne), to wiecie co, to nie jest jeszcze gotowe!

Radość trwa, gdy zdajesz sobie sprawę, że jeśli spróbujesz ustawić konkretny layout_widthlub layout_heightw swoim nowym, wymyślnym stylu, Android całkowicie to zignoruje !:

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

Aby ustawić SZCZEGÓLNĄ szerokość lub wysokość okna, musisz przejść do całej metody i poradzić sobie z 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);
}

Wielu ludzi podąża za złym przykładem Androida, rzucając WindowManager.LayoutParamssię na bardziej ogólne ViewGroup.LayoutParams, tylko po to, aby odwrócić się w prawo i rzucić z ViewGroup.LayoutParamspowrotem WindowManager.LayoutParamskilka linii później. Efektywna Java, niech cholera, to niepotrzebne rzutowanie nie oferuje NIC poza tym, że kod jest jeszcze trudniejszy do rozszyfrowania.

Uwaga dodatkowa: istnieje DWADZIEŚCIA powtórzeń LayoutParamscałego zestawu Android SDK - doskonały przykład radykalnie kiepskiego projektu.

W podsumowaniu

Z DialogFragmenttego powodu onCreateDialog:

  • Aby przywrócić standardowy AlertDialogwygląd i styl, utwórz styl, który ustawia background_color= transparenti layout_gravity= centeri zastosuj ten styl w programie onCreateDialog.
  • Aby ustawić określony layout_widthi / lub layout_height, zrobić programowo w onResumezLayoutParams
  • Aby zachować zdrowy rozsądek, staraj się nie myśleć o Android SDK.

13
Czytanie tej odpowiedzi sprawia, że ​​chcę płakać.
Bassinator,

3
Stary, dokładnie opisałeś, czego teraz doświadczam.
Mert Gülsoy

2
Android to gówno. Rozumiem to bracie. potrzebuję kontekstu dla wszystkiego, proces aplikacji zabija, brak bibliotek obsługujących niektóre rzeczy, lista jest długa
DennisVA,

1
@rmirabelle - ta odpowiedź faktycznie pomaga, właściwie możesz napisać średni blog i może być pomocna dla wielu. W moim przypadku używam układu ograniczeń i DialogFragment, więc z ignorowaniem w Androidzie 9, poniżej Androida 9 działa dobrze. Dodałem - "android: windowMinWidthMajor," android: windowMinWidthMinor "w stylu i zaczęło działać dobrze.
Rahul


14

Kiedy potrzebuję poszerzyć DialogFragment, ustawiam minWidth:

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

1
Najlepsze moim zdaniem rozwiązanie!
Fabian Knapp

co jeśli chcesz, aby była węższa?
Daniel

8

Nie widzę powód, aby zastąpić onResumelub onStartustawić szerokość i wysokość Windoww DialogFragment„s Dialog- te szczególne metody cyklu życia może się wielokrotnie i niepotrzebnie nazywa wykonać to zmiana rozmiaru kodu więcej niż raz z powodu wielu rzeczy, takich jak okna przełączania, w tło następnie ustawianie aplikacji na pierwszym planie i tak dalej. Konsekwencje tego powtórzenia są dość błahe, ale po co się na tym godzić?

Zamiast tego ustawienie szerokości / wysokości w ramach zastąpionej onActivityCreated()metody będzie ulepszeniem, ponieważ ta metoda jest realistycznie wywoływana tylko raz na instancję DialogFragment. Na przykład:

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

Powyżej ustawiłem szerokość match_parentniezależnie od orientacji urządzenia. Jeśli chcesz, aby okno dialogowe krajobrazu nie było tak szerokie, możesz getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAITwcześniej sprawdzić, czy .


6

Wymiar w układzie zewnętrznym nie działa w oknie dialogowym. Możesz dodać układ, w którym ustaw wymiar poniżej najbardziej zewnętrznego.

<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

Naprawiłem to ustawiając parametry układu głównego elementu.

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

5

Oto sposób ustawienia szerokości / wysokości DialogFragment w xml. Po prostu zawiń swój viewHierarchy w Framelayout (każdy układ będzie działał) z przezroczystym tłem.

Przezroczyste tło wydaje się być specjalną flagą, ponieważ automatycznie wyśrodkowuje element potomny frameLayout w oknie, gdy to zrobisz. Nadal będziesz mieć pełny ekran przyciemniony za swoim fragmentem, co oznacza, że ​​Twój fragment jest aktywnym elementem.

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

      .....

Spróbuję tego, ponieważ jeśli działa konsekwentnie, jest to ZASADNICZE lepsze podejście do kodowania części układu w XML, a część w kodzie. Dzięki
rmirabelle

Podoba mi się pomysł tego podejścia, ale podczas testowania daje inny układ niż zwykła programowa zmiana wysokości i szerokości. Na przykład całkowita szerokość jest siłą zmniejszana do maksymalnej szerokości zapewnianej przez AlertDialog (prawdopodobnie z powodu stylów Androida). Kiedy po prostu ustawię w i h za pomocą kodu, styl AlertDialog zostanie zastąpiony. Może to jednak pasować do wielu potrzeb i jest dobrym pomysłem. Niech żyje najgorszy SDK w historii.
rmirabelle

Działało świetnie dla onCreateView, dopóki nie chciałem zmienić wewnętrznej szerokości na match_parent ...
tudor

5

Oto wersja Kotlin

    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

Możesz użyć wartości procentowej dla szerokości.

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

W tym przykładzie użyłem Holo Theme.


3

Możesz poniżej kodu ustawić szerokość i wysokość układu z 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

Tworzę okno dialogowe za pomocą AlertDialog.Builder, więc użyłem odpowiedzi Rodrigo w 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));
            }

        });

(Głównie dla przyszłych czytelników :) Zobacz komentarz autorstwa Snicolasw dyskusji na temat „ DialogFragmentvs AlertDialog” na stackoverflow.com/a/7979823/3372061 .
Dev-iL

2

Pracując na Androidzie 6.0, napotkałem ten sam problem. AlertDialogbędzie domyślnie widthustawiać wstępnie zdefiniowany zestaw w kompozycji, niezależnie od rzeczywistego widthzestawu w katalogu głównym widoku niestandardowego Layout. Udało mi się dostać to, aby ustawić odpowiednio regulując widthz loading_message TextView. Bez dalszych badań wydaje się, że wymiarowanie rzeczywistych elementów i Layoutzawijanie wokół nich korzenia sprawia, że ​​działa zgodnie z oczekiwaniami. Poniżej znajduje się układ XML okna dialogowego ładowania, który widthprawidłowo ustawia okno dialogowe. Wykorzystanie tej biblioteki do animacji.

<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

Łatwe i solidne:

@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

W moim przypadku DialogFragmentzajęty pełny rozmiar działalności, taki jak a Fragment. DialogFragmentZostał oparty na XML-układ nie AlertDialog. Moim błędem było dodanie fragmentu okna dialogowego FragmentManagerjako zwykłego fragmentu:

fragmentManager?.beginTransaction()?.run {
    replace(R.id.container, MyDialogFragment.newInstance(), MyDialogFragment.TAG)
    addToBackStack(MyDialogFragment.TAG)
}?.commitAllowingStateLoss()

Zamiast tego potrzebuję showfragmentu dialogu:

val dialogFragment = MyDialogFragment.newInstance()
fragmentManager?.let { dialogFragment.show(it, MyDialogFragment.TAG) }

Po edycji (mam ViewPager2w układzie) fragment okna dialogowego stał się zbyt wąski:

wprowadź opis obrazu tutaj

Użyłem rozwiązania N1hk :

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)

    dialog?.window?.attributes?.width = ViewGroup.LayoutParams.MATCH_PARENT
}

Teraz ma zdefiniowaną szerokość i wysokość, a nie pełny rozmiar aktywności.

Chcę powiedzieć o onCreateViewi onCreateDialog. Jeśli masz fragment okna dialogowego oparty na układzie, możesz użyć dowolnej z tych dwóch metod.

1) Jeśli używasz onCreateView, powinieneś użyć onActivityCreateddo ustawienia szerokości.

2) Jeśli używasz onCreateDialogzamiast onCreateView, możesz ustawić tam parametry. onActivityCreatednie będą potrzebne.

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
}

Uratowałeś mi dzień, ustawiając szerokość w onActivityCreated działało dla mnie.
Hagar Magdy

@ManishKumarSharma, powodzenia!
CoolMind

1

W moim przypadku było to spowodowane align_parentBottom="true"widokiem wnętrza a RelativeLayout. Usunięto wszystkie alignParentBottom i zmieniono wszystkie układy na pionowe LinearLayouts i problem zniknął.


1

Ustaw nadrzędny układ niestandardowego układu dialogowego na RelativeLayout , automatycznie uzyskaj wspólną szerokość i wysokość.

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

To zadziałało dla mnie. Chciałem użyć ConstraintLayout do rozmieszczenia formantów w moim oknie dialogowym, więc użyłem RelativeLayout dla głównego układu, a następnie umieściłem ConstraintLayout bezpośrednio w nim. To dało mi normalne okno dialogowe. Kiedy umieściłem ConstraintLayout jako korzeń bez zmiany niczego innego, szerokość okna dialogowego implodowała do niezbyt szerokiej!
ścinacz liści

1

Jedno z wcześniejszych rozwiązań prawie zadziałało. Spróbowałem czegoś nieco innego i ostatecznie mi się to udało.

(Upewnij się, że spojrzałeś na jego rozwiązanie) To było jego rozwiązanie ... Kliknij tutaj . Zadziałało z wyjątkiem: builder.getContext (). GetTheme (). ApplyStyle (R.style.Theme_Window_NoMinWidth, true);

Zmieniłem to na

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

Ostatnia linia jest naprawdę inna.


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

To najprostsze rozwiązanie

Najlepszym rozwiązaniem, jakie znalazłem, jest zastąpienie onCreateDialog()zamiast onCreateView(). setContentView () ustawi poprawne wymiary okna przed zawyżeniem. Eliminuje potrzebę przechowywania / ustawiania wymiaru, koloru tła, stylu itp. W plikach zasobów i ustawiania ich ręcznie.

@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

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

To zadziała idealnie.

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

Tak właśnie mówi przyjęta odpowiedź sprzed ponad 3 lat.
Adil Hussain

-4

Aby uzyskać okno dialogowe obejmujące prawie cały osypisko: Najpierw zdefiniuj klasę 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;
    }
}

Następnie musisz wywołać ScreenParamater przed metodą getDialog.getWindow (). SetLayout ()

@Override
public void onResume()
{
    super.onResume();
    ScreenParameters s = new ScreenParameters();
    getDialog().getWindow().setLayout(s.Width , s.Height);
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.