Bagaimana cara mengatur lebar dan tinggi DialogFragment?


173

Saya menentukan tata letak DialogFragment saya dalam file tata letak xml (sebut saja layout_mydialogfragment.xml), layout_widthdan layout_heightatributnya dan khususnya ( 100dpmasing - masing katakanlah). Saya kemudian mengembang tata letak ini dalam onCreateView(...)metode DialogFragment saya sebagai berikut:

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

Sayangnya, saya menemukan bahwa ketika dialog saya (DialogFragment) muncul, itu tidak menghormati layout_widthdan layout_heightditentukan dalam file layout xml-nya (dan dialog saya menyusut atau meluas bervariasi tergantung pada konten). Ada yang tahu apakah atau bagaimana saya bisa mendapatkan dialog saya untuk menghormati layout_widthdan layout_heightditentukan dalam file layout xml-nya? Saat ini saya harus menentukan lagi lebar dan tinggi dialog saya dalam onResume()metode DialogFragment saya sebagai berikut ...

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

... Dan dengan demikian, tidak dapat disangkal, harus ingat untuk membuat perubahan di masa depan dengan lebar dan tinggi dialog di dua tempat.


2
Pertimbangkan untuk menerima jawaban jpmcosta. Ini bukan peretasan dan sebenarnya memperbaiki masalah.
Bogdan Zurac

Jawaban:


168

Jika Anda mengonversi langsung dari nilai sumber daya:

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

Kemudian tentukan match_parent di tata letak Anda untuk dialog:

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

Anda hanya perlu khawatir tentang satu tempat (letakkan di tempat Anda DialogFragment#onResume). Ini tidak sempurna, tetapi setidaknya berfungsi untuk memiliki RelativeLayout sebagai root dari file layout dialog Anda.


3
Jawaban ini tidak berfungsi dalam kasus saya (untuk DialogFragment). Saya harus menggunakan parem FragmentLayout untuk mengubah ukuran tampilan window.
Rusfearuth

3
Saya harus membungkus layout saya menjadi RelativeLayoutdan itu membantu saya. Terima kasih banyak atas solusinya - ini menyelamatkan saya banyak waktu.
Johnny Doe

62
Ini berfungsi baik untuk saya (Android 4.0+), begitu saya menyadari ini pasti ada onResume(), bukan onCreateView(). (Layout root saya adalah RelativeLayout terbungkus dalam ScrollView.)
Jonik

14
Berguna dalam beberapa kasus: gunakan seluruh lebar layar:int width = getResources().getDisplayMetrics().widthPixels
Jonik

6
+1 untuk Jonik. -1 untuk Richard. Saya selalu menggunakan fragmen dukungan dan tidak pernah bisa membuatnya bekerja onCreateDialog(). Kebutuhan untuk berada di onResume().
MinceMan

146

Saya akhirnya mengesampingkan Fragment.onResume()dan meraih atribut dari dialog yang mendasarinya, kemudian mengatur lebar / tinggi params di sana. Saya mengatur tinggi / lebar tata letak terluar ke match_parent. Perhatikan bahwa kode ini tampaknya juga menghargai margin yang saya tetapkan dalam tata letak 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
Terima kasih! Ini bekerja untuk saya! Apalagi ini adalah cara yang elegan untuk melakukannya.
AntoineP

1
@ jmaculate - Pertanyaan cepat: saat Anda casting (android.view.WindowManager.LayoutParams), dari mana Anda casting? Saya bingung ketika memilih impor yang benar untuk LayoutParamstampil di 3 baris pertama fungsi. Akhirnya memilih (android.view.WindowManager.LayoutParams). Apakah ini benar?
Dev-iL

@ Dev-iL getAttributes () mengembalikan WindowManger.LayoutParams, tetapi dalam kasus saya, saya secara implisit melemparkannya ke ViewGroup.LayoutParams karena hanya itu yang saya butuhkan (Java Efektif, Item 52) - Saya akan mengedit pertanyaan untuk mencerminkan ini
jmaculate

1
Jika Anda perlu membuangnya lagi android.view.WindowManager.LayoutParams, tidak ada gunanya menggunakan ViewGroup.LayoutParamstiga baris di atas ... Anda tidak mendapatkan fleksibilitas di sini. Terserah, terima kasih atas jawaban yang bagus ini!
Kevin Robatel

2
Ini solusi terbaik. Anda bahkan dapat menggunakan nilai piksel tertentu bersama dengan MATCH_PARENT atau WRAP_CONTENT.
Koesh

98

Saya mendapatkan DialogFragment ukuran tetap dengan mendefinisikan yang berikut ini dalam tata letak utama XML (LinearLayout dalam kasus saya):

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

4
Saya menemukan bahwa saya membutuhkan midWidth dan minHeight di Honeycomb - tetapi tidak di ICS.
daveywc

1
Sekilas ini tampaknya berfungsi tetapi mungkin harus dihindari. Tampilan akan berlanjut dari layar tergantung pada lebar perangkat jadi jika Anda memiliki tombol di sudut kanan bawah mereka tidak akan muncul.
CodyEngel

Tampilan TIDAK melanjutkan layar. Sistem android tampaknya memastikan bahwa DialogFragment tetap berada di dalam batas tampilan (dengan margin kecil), bahkan jika batas ini lebih kecil dari minWidth dan minHeight yang ditentukan.
Lensflare

51

Satu-satunya hal yang berhasil dalam kasus saya adalah solusi yang ditunjukkan di sini: http://adilatwork.blogspot.mx/2012/11/android-dialogfragment-dialog-sizing.html

Cuplikan dari posting blog 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
}

Solusi sempurna dan dijelaskan dengan sangat baik di blog.
varun bhardwaj

+1 getDialog().getWindow().setLayout(dialogWidth, dialogHeight); berfungsi dengan baik untuk DialogFragment. Tapi saya tidak mengerti pemeriksaan keamanannya. mengapa kita harus memeriksa null?
tpk

3
@ 2943 - hanya karena tidak ada jaminan bahwa Dialog(anak dari DialogFragment) akan tersedia pada saat diminta. Mungkin saja Android akan mengembalikan nol saat kami menelepon getDialog().
rmirabelle

@mirabelle jika Anda menggunakan panggilan balik onStart dialog bagaimana dialog bisa menjadi nol?
rommex

49

Salah satu cara untuk mengontrol DialogFragmentlebar dan tinggi Anda adalah dengan memastikan dialognya menghormati lebar dan tinggi tampilan Anda jika nilainya WRAP_CONTENT.

Menggunakan ThemeOverlay.AppCompat.Dialog

Salah satu cara sederhana untuk mencapai ini adalah dengan menggunakan ThemeOverlay.AppCompat.Dialoggaya yang termasuk dalam Perpustakaan Dukungan Android.

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

DialogFragmentdengan AlertDialog(peringatan:) 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();
}

Anda juga dapat menetapkan ThemeOverlay.AppCompat.Dialogsebagai tema default saat membuat dialog, dengan menambahkannya ke tema xml aplikasi Anda.
Hati-hati, karena banyak dialog membutuhkan lebar minimum default agar terlihat bagus.

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

DialogFragmentdengan Dialog, memanfaatkan 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;
}

DialogFragmentdengan AlertDialog, memanfaatkan android:alertDialogThemeatau alertDialogTheme(peringatan:) 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

Pada API Android Lama, Dialogtampaknya memiliki beberapa masalah lebar, karena judulnya (bahkan jika Anda tidak menyetelnya).
Jika Anda tidak ingin menggunakan ThemeOverlay.AppCompat.Dialoggaya dan Anda Dialogtidak perlu judul (atau memiliki judul khusus), Anda mungkin ingin menonaktifkannya:

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

Jawaban usang, tidak akan berfungsi dalam kebanyakan kasus

Saya mencoba untuk membuat dialog menghormati lebar dan tinggi tata letak saya, tanpa menentukan ukuran tetap secara pemrograman.

Saya tahu itu android:windowMinWidthMinordan android:windowMinWidthMajormenyebabkan masalah. Meskipun mereka tidak termasuk dalam tema saya Activityatau Dialog, mereka masih diterapkan pada Activitytema, entah bagaimana.

Saya datang dengan tiga solusi yang memungkinkan.

Solusi 1: buat tema dialog khusus dan gunakan saat membuat dialog di menu 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);
}

Solusi 2: buat tema khusus untuk digunakan dalam dialog ContextThemeWrapperyang akan berfungsi Context. Gunakan ini jika Anda tidak ingin membuat tema dialog khusus (misalnya, saat Anda ingin menggunakan tema yang ditentukan oleh 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());
}

Solusi 3 (dengan an AlertDialog): menegakkan android:windowMinWidthMinordan android:windowMinWidthMajorke dalam ContextThemeWrapperdiciptakan oleh 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
Saya benar-benar tidak tahu mengapa ini bukan jawaban yang diterima. Ini secara harfiah adalah satu-satunya jawaban yang berfungsi dan bukan peretasan (saya berbicara sebagian besar untuk solusi pertama Anda).
Bogdan Zurac

1
sayangnya menemukan ini hanya setelah menghabiskan satu jam mencari cara untuk menyelesaikannya!
brainvision

Solusi 3 menyelamatkan hidup saya. Terima kasih banyak
Simon

Saya dapat mereproduksi masalah Anda di API Android yang lebih lama. Menambahkan beberapa alternatif yang mungkin membantu Anda.
jpmcosta

Solusi 1 bekerja untuk saya. Saya hanya digunakan Theme.MaterialComponents.Light.Dialogsebagai orang tua dan menggunakan gaya ini di konstruktor MaterialAlertDialogBuilder. Menemukan jawaban Anda setelah penelitian 1 jam. Terima kasih dan acungan jempol.
Shahood ul Hassan

39

Gotcha # 13: DialogFragmentTata Letak

Pikiran semacam itu benar-benar mati rasa.

Saat membuat DialogFragment, Anda dapat memilih untuk mengganti onCreateView(yang meneruskan a ViewGroupuntuk melampirkan tata letak .xml Anda) atau onCreateDialog, yang tidak.

Anda tidak boleh mengesampingkan kedua metode itu, karena kemungkinan besar Anda akan membingungkan Android kapan atau jika tata letak dialog Anda meningkat! WTF?

Pilihan apakah akan menimpa OnCreateDialogatau OnCreateViewtergantung pada bagaimana Anda ingin menggunakan dialog.

  • Jika Anda akan meluncurkan dialog di jendela (perilaku normal), Anda diharapkan untuk menimpanya OnCreateDialog.
  • Jika Anda bermaksud menyematkan fragmen dialog dalam tata letak UI yang ada (JAUH lebih jarang), maka Anda diharapkan untuk menimpanya OnCreateView.

Ini mungkin hal terburuk di dunia.

onCreateDialog Penyakit jiwa

Jadi, Anda override onCreateDialogdi Anda DialogFragmentuntuk membuat sebuah instance disesuaikan AlertDialoguntuk tampilan dalam jendela. Keren. Tapi ingat, onCreateDialogtidak menerima ViewGroupuntuk melampirkan kustom Anda xml tata letak untuk . Tidak masalah, Anda cukup meneruskan nullke inflatemetode.

Biarkan kegilaan dimulai.

Saat Anda mengganti onCreateDialog, Android SEPENUHNYA MENGUMPULKAN beberapa atribut dari simpul akar Tata Letak .xml yang Anda kembangkan. Ini termasuk, tetapi mungkin tidak terbatas pada:

  • background_color
  • layout_gravity
  • layout_width
  • layout_height

Ini hampir lucu, karena Anda diharuskan untuk mengatur layout_widthdan layout_heightSETIAP .xml Layout atau Android Studio akan menampar Anda dengan lencana malu merah kecil yang bagus.

Hanya kata yang DialogFragment membuatku ingin muntah. Saya bisa menulis novel yang diisi dengan Android gotcha dan snafus, tetapi yang ini adalah salah satu yang paling dalam.

Untuk kembali ke kewarasan, pertama, kami menyatakan gaya untuk memulihkan HANYA background_colordan layout_gravitykami berharap:

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

Gaya di atas mewarisi dari tema dasar untuk Dialog (dalam AppCompattema dalam contoh ini).

Selanjutnya, kami menerapkan gaya pemrograman untuk mengembalikan nilai-nilai yang hanya dibuang Android dan mengembalikan AlertDialogtampilan dan nuansa standar :

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

Kode di atas akan membuat Anda AlertDialogterlihat seperti AlertDialoglagi. Mungkin ini cukup baik.

Tapi tunggu, masih ada lagi!

Jika Anda ingin menetapkan SPESIFIK layout_width atau layout_heightuntuk Anda AlertDialogketika itu ditampilkan (sangat mungkin), maka coba tebak, Anda belum selesai!

Keributan berlanjut ketika Anda menyadari bahwa jika Anda mencoba untuk menetapkan gaya tertentu layout_widthatau layout_heightgaya baru Anda, Android akan sepenuhnya mengabaikan itu juga !:

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

Untuk menetapkan lebar atau tinggi jendela KHUSUS, Anda dapat melanjutkan ke metode penggila keseluruhan dan berurusan dengan 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);
}

Banyak orang mengikuti contoh buruk Android untuk WindowManager.LayoutParamsmelakukan hal yang lebih umum ViewGroup.LayoutParams, hanya untuk berbalik dan ViewGroup.LayoutParamskembali ke WindowManager.LayoutParamsbeberapa baris kemudian. Efektif Java terkutuk, bahwa casting yang tidak perlu menawarkan TIDAK ADA selain membuat kode lebih sulit untuk diuraikan.

Catatan: Ada beberapa DUA PULUHAN pengulangan LayoutParamsdi Android SDK - contoh sempurna dari desain yang buruk secara radikal.

Singkatnya

Untuk DialogFragments yang menimpa onCreateDialog:

  • Untuk mengembalikan AlertDialogtampilan dan nuansa standar , buat gaya yang menetapkan background_color= transparentdan layout_gravity= centerdan terapkan gaya itu dalam onCreateDialog.
  • Untuk mengatur spesifik layout_widthdan / atau layout_height, melakukannya pemrograman di onResumedenganLayoutParams
  • Untuk menjaga kewarasan, cobalah untuk tidak memikirkan Android SDK.

13
Membaca jawaban ini membuat saya ingin menangis.
Bassinator

3
Kawan, kau jelaskan apa yang aku alami saat ini.
Mert Gülsoy

2
Android itu sial. Aku merasa kamu teman. membutuhkan konteks untuk semuanya, proses aplikasi mati, kurangnya dukungan perpustakaan untuk beberapa hal, daftarnya berlanjut
DennisVA

1
@rmirabelle - jawaban ini benar-benar membantu, Anda sebenarnya dapat menulis blog sedang, dan dapat bermanfaat bagi banyak orang. Dalam kasus saya, saya menggunakan tata letak kendala dan DialogFragment, jadi dengan mengabaikan di Android 9, di bawah Android 9 berfungsi dengan baik. Saya telah menambahkan - "android: windowMinWidthMajor," android: windowMinWidthMinor "dengan gaya dan mulai bekerja dengan baik.
Rahul


14

Ketika saya perlu membuat DialogFragment sedikit lebih lebar, saya menetapkan minWidth:

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

1
Solusi terbaik menurut saya!
Fabian Knapp

bagaimana jika Anda ingin membuatnya lebih sempit?
Daniel

8

Saya tidak melihat alasan kuat untuk menimpa onResumeatau onStartuntuk mengatur lebar dan tinggi dari Windowdalam DialogFragment's Dialog- metode ini siklus hidup tertentu dapat dipanggil berulang-ulang dan tidak perlu mengeksekusi yang mengubah ukuran kode lebih dari sekali karena hal-hal seperti multi window switching, pelatarbelakangan lalu foregrounding aplikasi, dan sebagainya. Konsekuensi dari pengulangan itu cukup sepele, tetapi mengapa puas dengan itu?

Mengatur lebar / tinggi sebagai gantinya dalam onActivityCreated()metode yang ditimpa akan menjadi perbaikan karena metode ini secara realistis hanya dipanggil sekali per instance dari Anda DialogFragment. Sebagai contoh:

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

Di atas saya hanya mengatur lebarnya match_parentterlepas dari orientasi perangkat. Jika Anda ingin dialog lanskap Anda tidak terlalu lebar, Anda dapat melakukan pengecekan apakah getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAITsebelumnya.


6

Dimensi dalam tata letak terluar tidak berfungsi dalam dialog. Anda dapat menambahkan tata letak tempat mengatur dimensi di bawah terluar.

<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

Saya memperbaikinya mengatur parameter tata letak elemen root.

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

5

Inilah cara untuk mengatur lebar / tinggi DialogFragment dalam xml. Hanya membungkus viewHierarchy Anda dalam Framelayout (tata letak apa pun akan berfungsi) dengan latar belakang transparan.

Latar belakang transparan tampaknya menjadi bendera khusus, karena secara otomatis memusatkan anak frameLayout di jendela ketika Anda melakukannya. Anda masih akan mendapatkan layar penuh gelap di belakang fragmen Anda, menunjukkan fragmen Anda adalah elemen aktif.

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

      .....

Saya akan mencoba ini karena jika bekerja secara konsisten, ini adalah pendekatan yang sangat unggul untuk mengkode bagian dari tata letak dalam XML dan bagian dari itu dalam kode. Terima kasih
rmirabelle

Saya menyukai ide pendekatan ini, tetapi ketika diuji, ia menghasilkan tata letak yang berbeda dari sekadar mengubah tinggi dan lebar secara terprogram. Misalnya, lebar keseluruhan secara paksa dikurangi menjadi lebar maks yang diberikan oleh AlertDialog (mungkin karena gaya Android). Ketika saya baru saja mengatur w dan h melalui kode, gaya AlertDialog ditolak. Namun ini mungkin cocok dengan banyak kebutuhan dan merupakan ide yang bagus. Hidup SDK terburuk dalam sejarah.
rmirabelle

Berfungsi bagus untuk onCreateView, sampai saya ingin mengubah lebar bagian dalam menjadi match_parent ...
tudor

5

Ini adalah versi 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

Anda dapat menggunakan persentase untuk lebar.

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

Saya menggunakan Holo Theme untuk contoh ini.


3

Anda dapat di bawah kode untuk mengatur lebar dan tinggi tata letak dari 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

Saya membuat dialog menggunakan AlertDialog.Builder jadi saya menggunakan jawaban Rodrigo di dalam 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));
            }

        });

(Terutama untuk pembaca masa depan :) Lihat komentar Snicolasdalam diskusi " DialogFragmentvs AlertDialog" di stackoverflow.com/a/7979823/3372061 .
Dev-iL

2

Bekerja pada Android 6.0, mengalami masalah yang sama. AlertDialogakan default ke widthset standar dalam tema terlepas dari widthset sebenarnya di root tampilan kustom Layout. Saya bisa mendapatkannya untuk mengatur benar menyesuaikan widthdari loading_message TextView. Tanpa menyelidiki lebih lanjut, tampaknya bahwa ukuran elemen yang sebenarnya dan Layoutmembungkus root di sekitar mereka membuatnya berfungsi seperti yang diharapkan. Di bawah ini adalah tata letak XML dari dialog pemuatan yang mengatur widthdialog dengan benar. Menggunakan perpustakaan ini untuk animasi.

<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

Mudah dan kokoh:

@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

Dalam kasus saya DialogFragmentditempati ukuran aktivitas penuh seperti a Fragment. Itu DialogFragmentdidasarkan pada tata letak XML, bukan AlertDialog. Kesalahan saya adalah menambahkan fragmen dialog FragmentManagersebagai fragmen biasa:

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

Alih-alih, saya perlu showfragmen dialog:

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

Setelah beberapa pengeditan (saya miliki ViewPager2dalam tata letak) fragmen dialog menjadi terlalu sempit:

masukkan deskripsi gambar di sini

Saya menggunakan solusi N1hk :

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

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

Sekarang telah ditentukan lebar dan tinggi, bukan ukuran aktivitas penuh.

Saya ingin katakan tentang onCreateViewdan onCreateDialog. Jika Anda memiliki fragmen dialog berdasarkan tata letak, Anda dapat menggunakan salah satu dari 2 metode ini.

1) Jika Anda menggunakan onCreateView, maka Anda harus menggunakan onActivityCreateduntuk mengatur lebar.

2) Jika Anda menggunakan onCreateDialogalih-alih onCreateView, Anda dapat mengatur parameter di sana. onActivityCreatedtidak akan dibutuhkan.

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
}

Anda menyelamatkan hari saya, mengatur lebar di onActivityCreated bekerja untuk saya.
Hagar Magdy

@ManishKumarSharma, semoga berhasil!
CoolMind

1

Dalam kasus saya itu disebabkan oleh align_parentBottom="true"diberikan ke tampilan di dalam a RelativeLayout. Menghapus semua alignParentBottom dan mengubah semua layout menjadi LinearLayouts vertikal dan masalah hilang.


1

Atur tata letak Induk dari tata letak dialog Kustom ke RelativeLayout , dapatkan lebar dan tinggi umum secara otomatis.

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

Ini berhasil untuk saya. Saya ingin menggunakan ConstraintLayout untuk meletakkan kontrol di dialog saya jadi saya menggunakan RelativeLayout untuk tata letak root dan kemudian meletakkan ConstraintLayout langsung di dalamnya. Ini memberi saya dialog berukuran normal. Ketika saya meletakkan ConstraintLayout sebagai root tanpa mengubah apa pun maka lebar dialognya tidak terlalu lebar!
pemotong daun

1

Salah satu solusi sebelumnya hampir berhasil. Saya mencoba sesuatu yang sedikit berbeda dan akhirnya berhasil untuk saya.

(Pastikan Anda melihat solusinya) Ini adalah solusinya .. Klik Di Sini Ini berfungsi kecuali untuk: builder.getContext (). GetTheme (). ApplyStyle (R.style.Theme_Window_NoMinWidth, true);

Saya mengubahnya menjadi

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

Baris terakhir adalah apa yang benar-benar berbeda.


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

Ini adalah solusi paling sederhana

Solusi terbaik yang saya temukan adalah menimpa onCreateDialog()alih-alih onCreateView(). setContentView () akan mengatur dimensi jendela yang benar sebelum menggembung. Ini menghilangkan kebutuhan untuk menyimpan / mengatur dimensi, warna latar belakang, gaya, dll dalam file sumber daya dan mengaturnya secara manual.

@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

Tambahkan ke Anda 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

Ini akan bekerja dengan sempurna.

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

Ini adalah apa yang dikatakan oleh jawaban yang diterima dari 3+ tahun yang lalu.
Adil Hussain

-4

Untuk mendapatkan Dialog yang mencakup hampir seluruh scree: Pertama tentukan kelas 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;
    }
}

Maka Anda harus memanggil ScreenParamater sebelum metode getDialog.getWindow (). SetLayout () Anda

@Override
public void onResume()
{
    super.onResume();
    ScreenParameters s = new ScreenParameters();
    getDialog().getWindow().setLayout(s.Width , s.Height);
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.