Wie stelle ich die Breite und Höhe von DialogFragment ein?


173

Ich spezifiziere das Layout meines DialogFragments in einer XML-Layoutdatei (nennen wir es layout_mydialogfragment.xml) und seine layout_widthund layout_heightAttribute besonders (um es 100dpjeweils zu sagen). Ich blase dieses Layout dann in der onCreateView(...)Methode meines DialogFragments wie folgt auf:

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

Leider stelle ich fest, dass mein Dialogfeld (DialogFragment) das in seiner XML-Layoutdatei angegebene layout_widthund layout_heightangegebene nicht berücksichtigt (und mein Dialogfeld je nach Inhalt unterschiedlich verkleinert oder erweitert wird). Weiß jemand, ob oder wie ich meinen Dialog dazu bringen kann, das zu respektieren layout_widthund layout_heightin seiner XML-Layoutdatei anzugeben? Im Moment muss ich die Breite und Höhe meines Dialogs in der onResume()Methode meines DialogFragments wie folgt erneut angeben ...

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

... Und daher müssen Sie in unerwünschter Weise daran denken, zukünftige Änderungen an der Breite und Höhe des Dialogfelds an zwei Stellen vorzunehmen.


2
Erwägen Sie, die Antwort von jpmcosta zu akzeptieren. Es ist kein Hack und behebt das Problem.
Bogdan Zurac

Antworten:


168

Wenn Sie direkt aus Ressourcenwerten konvertieren:

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

Geben Sie dann in Ihrem Layout match_parent für den Dialog an:

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

Sie müssen sich nur um einen Ort kümmern (platzieren Sie ihn in Ihrem DialogFragment#onResume). Es ist nicht perfekt, aber es funktioniert zumindest, wenn ein RelativeLayout als Stamm der Layoutdatei Ihres Dialogfelds verwendet wird.


3
Diese Antwort funktioniert in meinem Fall nicht (für DialogFragment). Ich musste FragmentLayout-Parameter verwenden, um die Größe des angezeigten Fensters zu ändern.
Rusfearuth

3
Ich musste mein Layout einpacken RelativeLayoutund es hat mir geholfen. Vielen Dank für die Lösung - das hat mir viel Zeit gespart.
Johnny Doe

62
Dies funktioniert gut für mich (Android 4.0 und höher), einmal wurde mir klar , das sein in muss onResume(), nicht onCreateView(). (Mein Root-Layout ist RelativeLayout in einer ScrollView.)
Jonik

14
In einigen Fällen nützlich: Verwenden Sie die gesamte Bildschirmbreite:int width = getResources().getDisplayMetrics().widthPixels
Jonik

6
+1 für Jonik. -1 für Richard. Ich verwende immer Unterstützungsfragmente und konnte dies nie zum Laufen bringen onCreateDialog(). Muss in sein onResume().
MinceMan

146

Fragment.onResume()Am Ende habe ich die Attribute aus dem zugrunde liegenden Dialogfeld überschrieben und abgerufen und dort die Parameter für Breite / Höhe festgelegt. Ich stelle die äußerste Layouthöhe / -breite auf ein match_parent. Beachten Sie, dass dieser Code anscheinend auch die Ränder berücksichtigt, die ich im XML-Layout definiert habe.

@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
Vielen Dank ! Für mich geht das ! Darüber hinaus ist dies eine elegante Art, dies zu tun.
AntoineP

1
@jmaculate - Kurze Frage: Wenn Sie Casting durchführen (android.view.WindowManager.LayoutParams), woraus werfen Sie es? Ich war verwirrt, als ich den richtigen Import für LayoutParamsdie ersten drei Zeilen der Funktion auswählte. Am Ende wählen (android.view.WindowManager.LayoutParams). Soll das richtig sein?
Dev-iL

@ Dev-iL getAttributes () gibt ein WindowManger.LayoutParams zurück, aber in meinem Fall habe ich es implizit in ViewGroup.LayoutParams umgewandelt, weil das alles ist, was ich brauche (Effective Java, Item 52) - Ich werde die Frage bearbeiten, um dies widerzuspiegeln
jmaculate

1
Wenn Sie es erneut umsetzen müssen android.view.WindowManager.LayoutParams, ist es sinnlos, ViewGroup.LayoutParamsdrei Zeilen oben zu verwenden ... Sie gewinnen hier keine Flexibilität. Wie auch immer, danke für diese gute Antwort!
Kevin Robatel

2
Dies ist die beste Lösung. Sie können sogar einen bestimmten Pixelwert zusammen mit MATCH_PARENT oder WRAP_CONTENT verwenden.
Koesh

98

Ich habe ein DialogFragment mit fester Größe erhalten, das Folgendes im XML-Hauptlayout definiert (in meinem Fall LinearLayout):

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

4
Ich stellte fest, dass ich die Mittelbreite und die Mindesthöhe in Honeycomb brauchte - aber nicht in ICS.
Daveywc

1
Dies scheint auf den ersten Blick zu funktionieren, sollte aber wahrscheinlich vermieden werden. Die Ansicht wird abhängig von der Gerätebreite außerhalb des Bildschirms fortgesetzt. Wenn Sie also Schaltflächen in der unteren rechten Ecke haben, werden diese nicht angezeigt.
CodyEngel

Die Ansicht wird NICHT außerhalb des Bildschirms fortgesetzt. Das Android-System scheint sicherzustellen, dass das DialogFragment innerhalb der Ansichtsgrenzen bleibt (mit einem kleinen Rand), auch wenn diese Grenzen kleiner als die angegebene minWidth und minHeight sind.
Lensflare

51

Das einzige, was in meinem Fall funktioniert hat, war die hier aufgezeigte Lösung: http://adilatwork.blogspot.mx/2012/11/android-dialogfragment-dialog-sizing.html

Ausschnitt aus dem Adil-Blogbeitrag:

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

Perfekte Lösung und sehr gut im Blog erklärt.
Varun Bhardwaj

+1 getDialog().getWindow().setLayout(dialogWidth, dialogHeight); funktioniert perfekt für ein DialogFragment. Aber ich verstehe die Sicherheitsüberprüfung nicht. warum müssen wir überprüfen null?
tpk

3
@ 2943 - einfach, weil es keine Garantie gibt, dass das Dialog(ein Kind von DialogFragment) zum gewünschten Zeitpunkt verfügbar ist. Es ist möglich, dass Android beim Aufruf null zurückgibt getDialog().
Rmirabelle

@mirabelle Wenn Sie den onStart-Rückruf des Dialogfelds ausführen, wie kann das Dialogfeld null sein?
Rommex

49

Eine Möglichkeit, die DialogFragmentBreite und Höhe Ihrer Ansicht zu steuern , besteht darin, sicherzustellen, dass der Dialog die Breite und Höhe Ihrer Ansicht berücksichtigt, wenn deren Wert gleich ist WRAP_CONTENT.

Verwenden von ThemeOverlay.AppCompat.Dialog

Eine einfache Möglichkeit, dies zu erreichen, besteht darin ThemeOverlay.AppCompat.Dialog, den in der Android Support Library enthaltenen Stil zu verwenden.

DialogFragmentmit 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 mit AlertDialog (Einschränkung :) 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();
}

Sie können ThemeOverlay.AppCompat.Dialogbeim Erstellen Ihrer Dialoge auch das Standarddesign festlegen , indem Sie es dem XML-Design Ihrer App hinzufügen.
Seien Sie vorsichtig, da viele Dialoge die Standard-Mindestbreite benötigen, um gut auszusehen.

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

DialogFragmentmit Dialog, Gebrauch machen vonandroid: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;
}

DialogFragmentmit AlertDialog, unter Verwendung von android:alertDialogThemeoder alertDialogTheme(Vorbehalt: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();
}

Bonus

Bei älteren Android-APIs Dialogscheinen s aufgrund ihres Titels einige Probleme mit der Breite zu haben (auch wenn Sie keine festlegen).
Wenn Sie keinen ThemeOverlay.AppCompat.DialogStil verwenden möchten und Dialogkeinen Titel benötigen (oder einen benutzerdefinierten haben), möchten Sie ihn möglicherweise deaktivieren:

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

Veraltete Antwort funktioniert in den meisten Fällen nicht

Ich habe versucht, den Dialog so zu gestalten, dass er die Breite und Höhe meines Layouts berücksichtigt, ohne programmgesteuert eine feste Größe anzugeben.

Ich habe das herausgefunden android:windowMinWidthMinorund android:windowMinWidthMajordas Problem verursacht. Obwohl sie nicht in meinem Activityoder meinem Thema enthalten waren, wurden sie irgendwie Dialogimmer noch auf das ActivityThema angewendet .

Ich habe drei mögliche Lösungen gefunden.

Lösung 1: Erstellen Sie ein benutzerdefiniertes Dialogthema und verwenden Sie es beim Erstellen des Dialogfelds in der 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);
}

Lösung 2: Erstellen Sie ein benutzerdefiniertes Thema, das in einem verwendet ContextThemeWrapperwerden soll, das als ContextDialogfeld dient. Verwenden Sie diese Option, wenn Sie kein benutzerdefiniertes Dialogthema erstellen möchten (z. B. wenn Sie das durch angegebene Thema verwenden möchten 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());
}

Lösung 3 (mit einem AlertDialog): erzwingen android:windowMinWidthMinorund android:windowMinWidthMajorin die ContextThemeWrappervon der 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
Ich weiß wirklich nicht, warum zum Teufel das nicht die akzeptierte Antwort ist. Dies ist buchstäblich DIE einzige Antwort, die funktioniert und kein Hack ist (ich spreche hauptsächlich für Ihre erste Lösung).
Bogdan Zurac

1
Leider fand ich das erst, nachdem ich eine Stunde damit verbracht hatte, herauszufinden, wie man es löst!
Brainvision

Lösung 3 rettet mein Leben. Vielen Dank
Simon

Ich konnte Ihr Problem auf älteren Android-APIs reproduzieren. Es wurden einige Alternativen hinzugefügt, die Ihnen helfen könnten.
jpmcosta

Lösung 1 hat bei mir funktioniert. Ich habe gerade Theme.MaterialComponents.Light.Dialogals Eltern verwendet und diesen Stil im Konstruktor von verwendet MaterialAlertDialogBuilder. Stolperte über Ihre Antwort nach einer Recherche von 1 Stunde. Danke und Daumen hoch.
Shahood ul Hassan vor

39

Gotcha # 13: DialogFragment Layouts

Es ist wirklich eine Art betäubender Geist.

Beim Erstellen von a DialogFragmentkönnen Sie wählen, ob Sie überschreiben möchten onCreateView(was a ViewGroupzum Anhängen Ihres XML-Layouts übergibt ) oder onCreateDialognicht.

Sie dürfen beide Methoden nicht überschreiben, da Sie Android sehr wahrscheinlich verwirren werden, wann oder ob das Layout Ihres Dialogs aufgeblasen wurde! WTF?

Die Wahl, ob überschrieben werden soll OnCreateDialogoder nicht, OnCreateViewhängt davon ab, wie Sie den Dialog verwenden möchten.

  • Wenn Sie den Dialog in einem Fenster starten (normales Verhalten), wird erwartet, dass Sie ihn überschreiben OnCreateDialog.
  • Wenn Sie beabsichtigen, das Dialogfragment in ein vorhandenes UI-Layout einzubetten (weitaus seltener), wird erwartet, dass Sie es überschreiben OnCreateView.

Dies ist möglicherweise das Schlimmste auf der Welt.

onCreateDialog Wahnsinn

Sie überschreiben also onCreateDialogIhre DialogFragment, um eine angepasste Instanz für AlertDialogdie Anzeige in einem Fenster zu erstellen . Cool. Aber denken Sie daran, onCreateDialogerhält nicht ViewGroupIhre Gewohnheit befestigen .xml Layout an . Kein Problem, Sie gehen einfach nullzuminflate Methode.

Lasst den Wahnsinn beginnen.

Wenn Sie überschreiben onCreateDialog, ignoriert Android VOLLSTÄNDIG mehrere Attribute des Stammknotens des von Ihnen aufgeblasenen XML-Layouts . Dies beinhaltet, ist aber wahrscheinlich nicht beschränkt auf:

  • background_color
  • layout_gravity
  • layout_width
  • layout_height

Dies ist fast komisch, da Sie das layout_widthund layout_heightvon JEDEM .xml-Layout einstellen müssen, oder Android Studio wird Sie mit einem schönen kleinen roten Abzeichen der Schande schlagen.

Allein das Wort DialogFragment bringt mich dazu zu kotzen. Ich könnte einen Roman schreiben, der mit Android-Fallstricken und Snafus gefüllt ist, aber dieser ist einer der innersten.

Um zur Vernunft zurückzukehren, erklären wir zunächst einen Stil, um NUR das wiederherzustellen, background_colorund layout_gravitywir erwarten:

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

Der obige Stil erbt vom Basisthema für Dialoge (im AppCompatThema in diesem Beispiel).

Als Nächstes wenden wir den Stil programmgesteuert an, um die Werte, die Android gerade beiseite geworfen hat, zurückzusetzen und das Standard-Erscheinungsbild wiederherzustellen 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();
    }
}

Der obige Code lässt Sie AlertDialogwieder wie ein aussehen AlertDialog. Vielleicht ist das gut genug.

Aber warte, da ist noch mehr!

Wenn Sie eine SPEZIFISCHE layout_width oder layout_heightfür Ihre festlegen möchtenAlertDialog wenn es (sehr wahrscheinlich) gezeigt ist, dann erraten , was ist man noch nicht fertig!

Die Heiterkeit setzt sich fort, wenn Sie feststellen, dass Android dies auch völlig ignoriert, wenn Sie versuchen, einen bestimmten layout_widthoder layout_heighteinen neuen Stil festzulegen!:

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

Um eine SPEZIFISCHE Fensterbreite oder -höhe festzulegen, müssen Sie zu einer ganz anderen Methode übergehen und sich mit Folgendem befassen 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);
}

Viele Leute folgen dem schlechten Beispiel von Android für das Casting WindowManager.LayoutParamsauf das Allgemeinere ViewGroup.LayoutParams, nur um sich nach rechts umzudrehen und ein paar Zeilen später ViewGroup.LayoutParamszurück zu werfen WindowManager.LayoutParams. Effektives Java, verdammt noch mal, dass unnötiges Casting NICHTS anderes bietet, als den Code noch schwerer zu entschlüsseln.

Randnotiz: Es gibt einige 20 Wiederholungen im LayoutParamsgesamten Android SDK - ein perfektes Beispiel für radikal schlechtes Design.

Zusammenfassend

Für DialogFragments, die überschreiben onCreateDialog:

  • AlertDialogErstellen Sie einen Stil, der background_color= transparentund layout_gravity= setzt, centerund wenden Sie diesen Stil an, um das Standard-Erscheinungsbild wiederherzustellen onCreateDialog.
  • Um ein bestimmtes layout_widthund / oder layout_heightfestzulegen, tun Sie dies programmgesteuert onResumemitLayoutParams
  • Denken Sie nicht an das Android SDK, um die Vernunft zu wahren.

13
Wenn ich diese Antwort lese, möchte ich weinen.
Bassinator

3
Alter, du hast genau beschrieben, was ich gerade erlebe.
Mert Gülsoy

2
Android ist Scheiße. Ich verstehe dich Kumpel. Sie brauchen einen Kontext für alles, App-Prozess-Kills, fehlende Support-Bibliotheken für einige Dinge, die Liste geht weiter
DennisVA

1
@rmirabelle - diese Antwort hilft tatsächlich, Sie können tatsächlich einen mittleren Blog schreiben und können für viele hilfreich sein. In meinem Fall verwende ich das Einschränkungslayout und DialogFragment. Mit Android 9 wurde es ignoriert. Unter Android 9 funktioniert es einwandfrei. Ich habe hinzugefügt - "android: windowMinWidthMajor", android: windowMinWidthMinor "im Stil und es begann gut zu funktionieren.
Rahul


14

Wenn ich das DialogFragment etwas breiter machen muss, setze ich minWidth:

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

1
Beste Lösung meiner Meinung nach!
Fabian Knapp

Was ist, wenn Sie es enger machen wollen?
Daniel

8

Ich sehe keinen zwingenden Grund außer Kraft zu setzen onResumeoder onStartdie Breite und Höhe des setzen Windowinnerhalb DialogFragment‚sDialog - diese besonderen Lebenszyklus - Methoden aufgerufen wiederholt bekommen können und unnötig ausführen , dass Code mehr als einmal wegen Dingen wie Multi - Fenster Schalen Ändern der Größe, Backgrounding dann Vordergrund der App und so weiter. Die Konsequenzen dieser Wiederholung sind ziemlich trivial, aber warum sollten Sie sich damit zufrieden geben?

Das Festlegen der Breite / Höhe stattdessen innerhalb einer überschriebenen onActivityCreated()Methode ist eine Verbesserung, da diese Methode realistischerweise nur einmal pro Instanz von Ihnen aufgerufen wird DialogFragment. Beispielsweise:

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

Oben habe ich nur die Breite so eingestellt, dass sie match_parentunabhängig von der Geräteorientierung ist. Wenn Ihr Landschaftsdialog nicht so breit sein soll, können Sie getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAITvorher prüfen, ob .


6

Die Dimension im äußersten Layout funktioniert im Dialog nicht. Sie können ein Layout hinzufügen, bei dem die Dimension unterhalb der äußersten festgelegt ist.

<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

Ich habe es behoben, indem ich die Layoutparameter des Stammelements festgelegt habe.

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

5

Hier ist eine Möglichkeit, die Breite / Höhe von DialogFragment in XML festzulegen. Wickeln Sie einfach Ihre viewHierarchy in ein Framelayout (jedes Layout funktioniert) mit einem transparenten Hintergrund.

Ein transparenter Hintergrund scheint ein besonderes Flag zu sein, da er das untergeordnete Element des frameLayout dabei automatisch im Fenster zentriert. Sie werden immer noch die Vollbild-Verdunkelung hinter Ihrem Fragment sehen, was darauf hinweist, dass Ihr Fragment das aktive Element ist.

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

      .....

Ich werde es versuchen, denn wenn es konsistent funktioniert, ist es ein SEHR überlegener Ansatz, einen Teil des Layouts in XML und einen Teil davon in Code zu codieren. Danke
rmirabelle

Ich mag die Idee dieses Ansatzes, aber wenn er getestet wird, ergibt er ein anderes Layout als das einfache programmgesteuerte Ändern von Höhe und Breite. Beispielsweise wird die Gesamtbreite zwangsweise auf die maximale Breite reduziert, die ein AlertDialog bietet (vermutlich aufgrund von Android-Stilen). Wenn ich w und h nur über Code setze, wird der AlertDialog-Stil außer Kraft gesetzt. Dies kann jedoch vielen Anforderungen gerecht werden und ist eine gute Idee. Es lebe das schlechteste SDK der Geschichte.
Rmirabelle

Arbeitete groß für onCreateView, bis ich die innere Breite match_parent ändern wollte ...
tudor

5

Hier ist die Kotlin-Version

    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

Sie können den Prozentsatz für die Breite verwenden.

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

Ich habe Holo Theme für dieses Beispiel verwendet.


3

Sie können den folgenden Code verwenden, um die Breite und Höhe des Layouts in Java festzulegen.

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

Ich erstelle den Dialog mit AlertDialog.Builder, also habe ich Rodrigos Antwort in einem OnShowListener verwendet.

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

        });

(Hauptsächlich für zukünftige Leser :) Siehe Kommentar von Snicolasin der Diskussion von " DialogFragmentvs AlertDialog" in stackoverflow.com/a/7979823/3372061 .
Dev-iL

2

Bei der Arbeit mit Android 6.0 ist das gleiche Problem aufgetreten. AlertDialogStandardmäßig wird ein vordefinierter widthSatz im Design verwendet, unabhängig vom tatsächlichen widthSatz im Stammverzeichnis der benutzerdefinierten Ansicht Layout. Ich war in der Lage , um es richtig zu setzen die Einstellung widthder loading_message TextView. Ohne weitere Untersuchungen durchzuführen, scheint es so zu sein, dass die Größe der tatsächlichen Elemente und das LayoutUmwickeln mit der Wurzel wie erwartet funktioniert. Unten finden Sie ein XML-Layout eines Ladedialogs, widthin dem der Dialog korrekt eingestellt ist. Verwenden dieser Bibliothek für die Animation.

<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

Einfach und solide:

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

1

In meinem Fall wurde es durch align_parentBottom="true"einen Blick in ein gegeben RelativeLayout. Alle alignParentBottom's wurden entfernt und alle Layouts in vertikale LinearLayouts geändert. Das Problem ist behoben.


1

Stellen Sie das übergeordnete Layout des benutzerdefinierten Dialoglayouts auf RelativeLayout ein und ermitteln Sie automatisch die allgemeine Breite und Höhe.

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

Das hat bei mir funktioniert. Ich wollte ein ConstraintLayout verwenden, um die Steuerelemente in meinem Dialogfeld anzuordnen, also habe ich ein RelativeLayout für das Root-Layout verwendet und dann ein ConstraintLayout direkt darin eingefügt. Dies gab mir einen normal großen Dialog. Wenn ich das ConstraintLayout als Root verwende, ohne etwas anderes zu ändern, ist die Dialogbreite nicht sehr breit implodiert!
Blattschneider

1

Eine der früheren Lösungen hat fast funktioniert. Ich habe etwas anderes ausprobiert und es hat bei mir funktioniert.

( Stellen Sie sicher, dass Sie sich seine Lösung ansehen.) Dies war seine Lösung. Klicken Sie hier. Es funktionierte mit Ausnahme von: builder.getContext (). GetTheme (). ApplyStyle (R.style.Theme_Window_NoMinWidth, true);

Ich habe es geändert in

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

Die letzte Zeile ist wirklich anders.


1

In meinem Fall DialogFragmentbesetzte volle Aktivitätsgröße wie ein Fragment. Das DialogFragmentbasierte auf XML-Layout, nicht AlertDialog. Mein Fehler war das Hinzufügen des Dialogfragments zu FragmentManagereinem normalen Fragment:

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

Stattdessen muss ich zum showDialogfragment:

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

Nach einiger Bearbeitung (ich habe ViewPager2im Layout) wurde das Dialogfragment zu schmal:

Geben Sie hier die Bildbeschreibung ein

Ich habe die Lösung von N1hk verwendet :

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

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

Jetzt hat es Breite und Höhe definiert, nicht die volle Aktivitätsgröße.

Ich möchte über onCreateViewund sagen onCreateDialog. Wenn Sie ein auf dem Layout basierendes Dialogfragment haben, können Sie eine dieser beiden Methoden verwenden.

1) Wenn Sie verwenden onCreateView, sollten Sie verwenden onActivityCreated, um die Breite einzustellen.

2) Wenn Sie onCreateDialoganstelle von verwenden onCreateView, können Sie dort Parameter einstellen. onActivityCreatedwird nicht benötigt.

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
}

Sie haben meinen Tag gerettet und die Breite in onActivityCreated festgelegt.
Hagar Magdy

@ HagMagdy, froh es zu hören!
CoolMind

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

Dies ist die einfachste Lösung

Die beste Lösung, die ich gefunden habe, ist das Überschreiben onCreateDialog()anstelle von onCreateView(). setContentView () legt vor dem Aufblasen die richtigen Fensterabmessungen fest. Es entfällt die Notwendigkeit, eine Dimension, Hintergrundfarbe, einen Stil usw. in Ressourcendateien zu speichern / festzulegen und manuell festzulegen.

@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

Fügen Sie Ihrem hinzu 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

Dies wird perfekt funktionieren.

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

Dies ist so ziemlich das, was die akzeptierte Antwort von vor mehr als 3 Jahren sagt.
Adil Hussain

-4

So erhalten Sie einen Dialog, der fast das gesamte Geröll abdeckt: Definieren Sie zunächst eine ScreenParameter-Klasse

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

Dann müssen Sie den ScreenParamater vor Ihrer Methode getDialog.getWindow (). SetLayout () aufrufen

@Override
public void onResume()
{
    super.onResume();
    ScreenParameters s = new ScreenParameters();
    getDialog().getWindow().setLayout(s.Width , s.Height);
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.