Làm cách nào để đặt chiều rộng và chiều cao của DialogFragment?


173

Tôi chỉ định bố cục DialogFragment của mình trong tệp bố cục xml (hãy gọi nó là layout_mydialogfragment.xml) layout_widthlayout_heightđặc biệt là các thuộc tính của nó ( 100dpmỗi loại hãy nói). Sau đó tôi sẽ tăng bố cục này trong onCreateView(...)phương thức DialogFragment của tôi như sau:

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

Thật không may, tôi thấy rằng khi hộp thoại của tôi (DialogFragment) xuất hiện, nó không tôn trọng layout_widthlayout_heightđược chỉ định trong tệp bố cục xml của nó (và hộp thoại của tôi thu nhỏ hoặc mở rộng tùy theo nội dung). Bất cứ ai cũng biết liệu tôi có thể làm cho hộp thoại của mình tôn trọng layout_widthlayout_heightđược chỉ định trong tệp bố cục xml của nó không? Hiện tại tôi phải xác định lại chiều rộng và chiều cao của hộp thoại trong onResume()phương thức DialogFragment của mình như sau ...

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

... Và do đó, không mong muốn, phải nhớ thực hiện bất kỳ thay đổi nào trong tương lai đối với chiều rộng và chiều cao của hộp thoại ở hai nơi.


2
Xem xét chấp nhận câu trả lời của jpmcosta. Nó không phải là một hack và nó thực sự khắc phục vấn đề.
Bogdan Zurac

Câu trả lời:


168

Nếu bạn chuyển đổi trực tiếp từ các giá trị tài nguyên:

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

Sau đó chỉ định match_parent trong bố cục của bạn cho hộp thoại:

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

Bạn chỉ phải lo lắng về một nơi (đặt nó trong của bạn DialogFragment#onResume). Nó không hoàn hảo, nhưng ít nhất nó hoạt động để có RelativeLayout làm gốc của tệp bố cục hộp thoại của bạn.


3
Câu trả lời này không hoạt động trong trường hợp của tôi (đối với DialogFragment). Tôi đã phải sử dụng thông số FragmentLayout để thay đổi kích thước cửa sổ hiển thị.
Rusfearuth

3
Tôi đã phải bọc bố cục của tôi vào RelativeLayoutvà nó đã giúp tôi. Rất cám ơn về giải pháp - nó đã tiết kiệm cho tôi rất nhiều thời gian.
Johnny Doe

62
Điều này hoạt động rất tốt đối với tôi (Android 4.0+), một khi tôi nhận ra điều này phải có onResume(), không phải onCreateView(). (Bố cục gốc của tôi là RelativeLayout được bao bọc trong ScrollView.)
Jonik

14
Hữu ích trong một số trường hợp: sử dụng toàn bộ chiều rộng màn hình:int width = getResources().getDisplayMetrics().widthPixels
Jonik

6
+1 cho Jonik. -1 cho Richard. Tôi luôn sử dụng các đoạn hỗ trợ và chưa bao giờ có thể làm việc này onCreateDialog(). Cần phải ở trong onResume().
MinceMan

146

Tôi đã kết thúc việc ghi đè Fragment.onResume()và lấy các thuộc tính từ hộp thoại bên dưới, sau đó đặt tham số chiều rộng / chiều cao ở đó. Tôi đặt chiều cao / chiều rộng bố trí ngoài cùng thành match_parent. Lưu ý rằng mã này dường như cũng tôn trọng các lề tôi đã xác định trong bố cục 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
Cảm ơn ! Nó làm việc cho tôi! Hơn nữa đây là một cách thanh lịch để làm điều đó.
AntoineP

1
@jmaculate - Câu hỏi nhanh: khi bạn đang casting (android.view.WindowManager.LayoutParams), bạn đang chọn nó từ đâu? Tôi đã bối rối khi chọn nhập chính xác để LayoutParamsxuất hiện trong 3 dòng đầu tiên của chức năng. Đã kết thúc lựa chọn (android.view.WindowManager.LayoutParams). Đây có phải là chính xác?
Dev-iL

@ Dev-iL getAttribut () trả về WindowManger.LayoutParams, nhưng trong trường hợp của tôi, tôi đã ngầm gửi nó cho Viewgroup.LayoutParams vì đó là tất cả những gì tôi cần (Java hiệu quả, Mục 52) - Tôi sẽ chỉnh sửa câu hỏi để phản ánh điều này
jmaculation

1
Nếu bạn cần sử dụng lại lần nữa android.view.WindowManager.LayoutParams, sẽ vô ích khi sử dụng ViewGroup.LayoutParamsba dòng trên ... Bạn không có được sự linh hoạt nào ở đây. Sao cũng được, cảm ơn bạn vì câu trả lời tốt này!
Kevin Robatel 7/10/2015

2
Đây là giải pháp tốt nhất. Bạn thậm chí có thể sử dụng một giá trị pixel cụ thể cùng với MATCH_PARENT hoặc WRAP_CONTENT.
Koesh

98

Tôi đã nhận được DialogFragment có kích thước cố định xác định các mục sau trong bố cục chính XML (linearLayout trong trường hợp của tôi):

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

4
Tôi thấy rằng tôi cần midWidth và minHeight trong Honeycomb - nhưng không phải trong ICS.
daveywc

1
Điều này có vẻ hoạt động từ cái nhìn đầu tiên nhưng có lẽ nên tránh. Chế độ xem sẽ tiếp tục tắt màn hình tùy thuộc vào độ rộng của thiết bị, vì vậy nếu bạn có các nút ở góc dưới bên phải, chúng sẽ không xuất hiện.
CodyEngel

Chế độ xem KHÔNG tiếp tục tắt màn hình. Hệ thống Android dường như đảm bảo rằng DialogFragment nằm trong giới hạn chế độ xem (với một lề nhỏ), ngay cả khi các giới hạn này nhỏ hơn giới hạn minWidth và minHeight được chỉ định.
Lensflare

51

Điều duy nhất làm việc trong trường hợp của tôi là giải pháp được chỉ ra ở đây: http://adilatwork.blogspot.mx/2012/11/android-dialogfragment-dialog-sizing.html

Đoạn trích từ bài đăng trên blog của 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
}

Giải pháp hoàn hảo và được giải thích rất tốt trong blog.
varun bhardwaj

+1 getDialog().getWindow().setLayout(dialogWidth, dialogHeight); hoạt động hoàn hảo cho DialogFragment. Nhưng tôi không hiểu kiểm tra an toàn. Tại sao chúng ta phải kiểm tra null?
tpk

3
@ 2943 - đơn giản vì không có gì đảm bảo rằng Dialog(một đứa trẻ của DialogFragment) sẽ có sẵn tại thời điểm nó được yêu cầu. Có thể Android sẽ trả về null khi chúng tôi gọi getDialog().
rmirabelle

@mirabelle nếu bạn đang hủy bỏ cuộc gọi lại onStart của hộp thoại, làm thế nào hộp thoại có thể là null?
rommex

49

Một cách để kiểm soát DialogFragmentchiều rộng và chiều cao của bạn là đảm bảo hộp thoại của nó tôn trọng chiều rộng và chiều cao của chế độ xem của bạn nếu giá trị của chúng làWRAP_CONTENT .

Sử dụng ThemeOverlay.AppCompat.Dialog

Một cách đơn giản để đạt được điều này là sử dụng ThemeOverlay.AppCompat.Dialogphong cách có trong Thư viện hỗ trợ Android.

DialogFragmentvới 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;
}

DialogFragmentvới AlertDialog(báo trước 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();
}

Bạn cũng có thể đặt ThemeOverlay.AppCompat.Dialoglàm chủ đề mặc định khi tạo các hộp thoại của mình, bằng cách thêm nó vào chủ đề xml của ứng dụng.
Hãy cẩn thận, vì nhiều hộp thoại cần chiều rộng tối thiểu mặc định để trông tốt.

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

DialogFragmentvới Dialog, sử dụng 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;
}

DialogFragmentvới AlertDialog, sử dụng android:alertDialogThemehoặc alertDialogTheme(báo trước 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();
}

Tặng kem

Trên các API Android cũ hơn, Dialogdường như có một số vấn đề về chiều rộng, do tiêu đề của chúng (ngay cả khi bạn không đặt).
Nếu bạn không muốn sử dụng ThemeOverlay.AppCompat.Dialogkiểu và bạn Dialogkhông cần một tiêu đề (hoặc có một tùy chỉnh), bạn có thể muốn tắt nó:

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

Câu trả lời lỗi thời, sẽ không hoạt động trong hầu hết các trường hợp

Tôi đã cố gắng làm cho hộp thoại tôn trọng chiều rộng và chiều cao của bố cục của tôi, mà không chỉ định kích thước cố định theo chương trình.

Tôi đã tìm ra điều đó android:windowMinWidthMinorandroid:windowMinWidthMajorđang gây ra vấn đề. Mặc dù chúng không được bao gồm trong chủ đề của tôi Activityhoặc Dialog, chúng vẫn đang được áp dụng cho Activitychủ đề này, bằng cách nào đó.

Tôi đã đưa ra ba giải pháp có thể.

Giải pháp 1: tạo chủ đề hộp thoại tùy chỉnh và sử dụng nó khi tạo hộp thoại trong 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);
}

Giải pháp 2: tạo một chủ đề tùy chỉnh sẽ được sử dụng trong một chủ đề ContextThemeWrappersẽ phục vụ như Contextcho hộp thoại. Sử dụng điều này nếu bạn không muốn tạo một chủ đề hộp thoại tùy chỉnh (ví dụ: khi bạn muốn sử dụng chủ đề được chỉ định bởi 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());
}

Giải pháp 3 (với một AlertDialog): thực thi android:windowMinWidthMinorandroid:windowMinWidthMajorvào ContextThemeWrapperđược tạo bởi 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
Tôi thực sự không biết tại sao địa ngục này không phải là câu trả lời được chấp nhận. Đây đúng là câu trả lời duy nhất hoạt động và không phải là hack (tôi đang nói chủ yếu cho giải pháp đầu tiên của bạn).
Bogdan Zurac

1
Thật không may tìm thấy điều này chỉ sau khi dành một giờ để tìm cách giải quyết!
cân não ngày

Giải pháp 3 cứu mạng tôi. Cảm ơn bạn rất nhiều
Simon

Tôi đã có thể tái tạo vấn đề của bạn trên các API Android cũ hơn. Đã thêm một số lựa chọn thay thế có thể giúp bạn.
jpmcosta

Giải pháp 1 làm việc cho tôi. tôi chỉ sử dụng Theme.MaterialComponents.Light.Dialognhư cha mẹ và sử dụng phong cách này trong hàm tạo của MaterialAlertDialogBuilder. Tình cờ nhận được câu trả lời của bạn sau khi nghiên cứu 1 giờ. Cảm ơn và đưa ngón tay cái lên.
Shahood ul Hassan

39

Gotcha # 13: DialogFragment Bố cục

Đó là loại tâm trí tê liệt thực sự.

Khi tạo a DialogFragment, bạn có thể chọn ghi đè onCreateView(vượt qua a ViewGroupđể đính kèm bố cục .xml của bạn) hoặc onCreateDialogkhông.

Bạn không được ghi đè cả hai phương thức tho, vì rất có thể bạn sẽ nhầm lẫn Android là khi nào hoặc nếu bố cục hộp thoại của bạn bị thổi phồng! WTF?

Việc lựa chọn ghi đè OnCreateDialoghay OnCreateViewphụ thuộc vào cách bạn định sử dụng hộp thoại.

  • Nếu bạn sẽ khởi chạy hộp thoại trong một cửa sổ (hành vi bình thường), bạn sẽ phải ghi đè OnCreateDialog.
  • Nếu bạn có ý định nhúng đoạn hộp thoại trong bố cục UI hiện có (FAR ít phổ biến hơn), thì bạn sẽ phải ghi đè OnCreateView.

Đây có thể là điều tồi tệ nhất trên thế giới.

onCreateDialog Chứng điên cuồng

Vì vậy, bạn đang trọng onCreateDialogtrong bạn DialogFragmentđể tạo ra một trường hợp tùy chỉnh của AlertDialogmàn hình hiển thị trong một cửa sổ. Mát mẻ. Nhưng hãy nhớ, onCreateDialogkhông nhận được ViewGroupđể đính kèm bố cục .xml tùy chỉnh của bạn vào . Không có vấn đề, bạn chỉ cần vượt qua nullđểinflate phương thức.

Hãy để sự điên rồ bắt đầu.

Khi bạn ghi đè onCreateDialog, Android HOÀN TOÀN KIẾM một số thuộc tính của nút gốc của Bố cục .xml mà bạn thực hiện. Điều này bao gồm, nhưng có lẽ không giới hạn ở:

  • background_color
  • layout_gravity
  • layout_width
  • layout_height

Điều này gần như là hài hước, vì bạn được yêu cầu thiết lập layout_widthlayout_heightMỌI Bố cục .xml hoặc Android Studio sẽ tát bạn với một huy hiệu nhỏ màu đỏ đáng xấu hổ.

Chỉ từ DialogFragment làm cho tôi muốn nôn. Tôi có thể viết một cuốn tiểu thuyết chứa đầy Android gotchas và snafus, nhưng đây là một trong những cuốn hay nhất.

Để trở lại sự tỉnh táo, trước tiên, chúng tôi tuyên bố một phong cách để khôi phục CHỈ background_colorlayout_gravitychúng tôi mong đợi:

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

Kiểu ở trên kế thừa từ chủ đề cơ sở cho Hộp thoại (trong AppCompatchủ đề trong ví dụ này).

Tiếp theo, chúng tôi áp dụng kiểu lập trình để đặt lại các giá trị mà Android vừa gạt sang một bên và để khôi phục AlertDialoggiao diện chuẩn :

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

Các mã ở trên sẽ làm cho bạn AlertDialogtrông giống như một AlertDialoglần nữa. Có lẽ điều này là đủ tốt.

Nhưng xin chờ chút nữa!

Nếu bạn đang tìm cách đặt CỤ THỂ layout_width hoặc layout_heightchoAlertDialog khi nó được hiển thị (rất có thể), thì hãy đoán xem, bạn vẫn chưa hoàn thành!

Sự vui nhộn tiếp tục khi bạn nhận ra rằng nếu bạn cố gắng đặt một cụ thể layout_widthhoặc layout_heighttheo phong cách mới lạ mắt của mình, Android cũng sẽ hoàn toàn bỏ qua điều đó!:

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

Để đặt chiều rộng hoặc chiều cao cửa sổ CỤ THỂ, bạn phải tìm đến một phương pháp toàn diện hơn và xử lý 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);
}

Nhiều người theo gương xấu của Android về việc đưa WindowManager.LayoutParamsra một cách tổng quát hơn ViewGroup.LayoutParams, chỉ để quay lại và ViewGroup.LayoutParamsquay trở lại WindowManager.LayoutParamsmột vài dòng sau đó. Java hiệu quả bị nguyền rủa, việc truyền không cần thiết cung cấp KHÔNG CÓ gì ngoài việc làm cho mã thậm chí khó giải mã hơn.

Lưu ý bên lề: Có một số lần lặp lại HAI LẦN LayoutParamstrên SDK Android - một ví dụ hoàn hảo về thiết kế hoàn toàn kém.

Tóm tắt

Đối với DialogFragments ghi đè onCreateDialog:

  • Để khôi phục AlertDialoggiao diện chuẩn , hãy tạo một kiểu đặt background_color= transparentlayout_gravity= centervà áp dụng kiểu đó vào onCreateDialog.
  • Để đặt một cụ thể layout_widthvà / hoặc layout_height, hãy lập trình onResumevớiLayoutParams
  • Để duy trì sự tỉnh táo, hãy cố gắng không nghĩ về SDK Android.

13
Đọc câu trả lời này khiến tôi muốn khóc.
Bassinator

3
Anh bạn, đã mô tả chính xác những gì tôi đang trải nghiệm ngay bây giờ.
Mert Gülsoy

2
Android là cứt. Tôi cảm thấy bạn bro. cần một bối cảnh cho tất cả mọi thứ, giết chết quá trình ứng dụng, thiếu thư viện hỗ trợ cho một số thứ, danh sách sẽ tiếp tục
DennisVA

1
@rmirabelle - câu trả lời này thực sự hữu ích, bạn thực sự có thể viết một blog vừa và có thể hữu ích cho nhiều người. Trong trường hợp của tôi, tôi đang sử dụng bố cục ràng buộc và DialogFragment, do đó, đã bị bỏ qua trong Android 9, bên dưới Android 9, nó hoạt động tốt. Tôi đã thêm - "android: windowMinWidthMajor," android: windowMinWidthMinor "theo phong cách và nó bắt đầu hoạt động tốt.
Rahul


14

Khi tôi cần làm cho DialogFragment rộng hơn một chút, tôi sẽ đặt minWidth:

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

1
Giải pháp tốt nhất theo ý kiến ​​của tôi!
Fabian Knapp

Điều gì nếu bạn muốn làm cho nó hẹp hơn?
Daniel

8

Tôi không thấy một lý do thuyết phục để ghi đè lên onResumehoặc onStartđể thiết lập chiều rộng và chiều cao của Windowtrong DialogFragment's Dialog- những phương pháp vòng đời cụ thể có thể được gọi nhiều lần và không cần thiết thực hiện mà thay đổi kích thước mã hơn một lần do những thứ như chuyển mạch đa cửa sổ, backgrounding sau đó tạo tiền đề cho ứng dụng, v.v. Hậu quả của sự lặp lại đó là khá nhỏ, nhưng tại sao lại giải quyết cho điều đó?

Thay vào đó, đặt chiều rộng / chiều cao trong một onActivityCreated()phương thức được ghi đè sẽ là một sự cải tiến vì phương thức này thực tế chỉ được gọi một lần cho mỗi phiên bản của bạn DialogFragment. Ví dụ:

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

Ở trên tôi chỉ đặt chiều rộng là match_parentkhông phân biệt hướng thiết bị. Nếu bạn muốn hộp thoại ngang của bạn không quá rộng, bạn có thể kiểm tra xem getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAITtrước.


6

Kích thước trong bố cục ngoài cùng không hoạt động trong hộp thoại. Bạn có thể thêm bố cục trong đó đặt kích thước bên dưới ngoài cùng.

<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

Tôi đã sửa nó thiết lập các tham số bố trí phần tử gốc.

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

5

Đây là một cách để đặt chiều rộng / chiều cao của DialogFragment trong xml. Chỉ cần bọc chế độ xem của bạn trong Framelayout (mọi bố cục sẽ hoạt động) với nền trong suốt.

Một nền trong suốt dường như là một lá cờ đặc biệt, bởi vì nó tự động căn giữa con của frameLayout trong cửa sổ khi bạn làm điều đó. Bạn vẫn sẽ có được toàn màn hình tối phía sau mảnh của bạn, cho biết mảnh của bạn là yếu tố hoạt động.

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

      .....

Tôi sẽ thử làm điều này bởi vì nếu nó hoạt động ổn định, thì đó là một cách tiếp cận vượt trội VASTLY để mã hóa một phần bố cục trong XML và một phần của nó trong mã. Cảm ơn
rmirabelle

Tôi thích ý tưởng của phương pháp này, nhưng khi thử nghiệm, nó mang lại một bố cục khác thay vì chỉ đơn giản là thay đổi chiều cao và chiều rộng theo chương trình. Chẳng hạn, chiều rộng tổng thể bị giảm xuống mức chiều rộng tối đa mà AlertDialog cung cấp (có lẽ là do các kiểu Android). Khi tôi chỉ đặt w và h qua mã, kiểu AlertDialog sẽ bị ghi đè. Điều này có thể phù hợp với nhiều nhu cầu tuy nhiên và là một ý tưởng tốt. Sống lâu SDK tồi tệ nhất trong lịch sử.
rmirabelle

Hoạt động rất tốt cho onCreateView, cho đến khi tôi muốn thay đổi độ rộng bên trong thành match_parent ...
tudor

5

Đây là phiên bản 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

Bạn có thể sử dụng tỷ lệ phần trăm cho chiều rộng.

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

Tôi đã sử dụng Holo Theme cho ví dụ này.


3

Bạn có thể bên dưới mã để đặt chiều rộng và chiều cao bố cục từ 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

Tôi tạo hộp thoại bằng AlertDialog.Builder vì vậy tôi đã sử dụng câu trả lời của Rodrigo bên trong 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));
            }

        });

(Chủ yếu dành cho độc giả tương lai :) Xem bình luận bằng cách Snicolasthảo luận về " DialogFragmentvs AlertDialog" trong stackoverflow.com/a/7979823/3372061 .
Dev-iL

2

Làm việc trên Android 6.0, gặp vấn đề tương tự. AlertDialogsẽ mặc định cho widthtập được xác định trước trong chủ đề bất kể tập thực tế widthtrong thư mục gốc của chế độ xem tùy chỉnh Layout. Tôi đã có thể để có được nó để thiết lập điều chỉnh đúng widthcủa loading_message TextView. Không cần điều tra thêm, có vẻ như kích thước các yếu tố thực tế và có gốcLayout bao quanh chúng làm cho nó hoạt động như mong đợi. Dưới đây là cách bố trí XML của hộp thoại tải, bộ này đặt widthchính xác hộp thoại. Sử dụng thư viện này cho hình ảnh động.

<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

Dễ dàng và vững chắc:

@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

Trong trường hợp của tôi, nó được gây ra bởi align_parentBottom="true"một quan điểm bên trong a RelativeLayout. Đã xóa tất cả các alignParentBottom và thay đổi tất cả các bố cục thành linearLayouts dọc và vấn đề đã biến mất.


1

Đặt bố cục gốc của bố cục hội thoại tùy chỉnh thành RelativeLayout , tự động nhận chiều rộng và chiều cao chung.

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

Điều này làm việc cho tôi. Tôi muốn sử dụng ConstraintLayout để bố trí các điều khiển trong hộp thoại của mình vì vậy tôi đã sử dụng RelativeLayout cho bố cục gốc và sau đó đặt ConstraintLayout trực tiếp bên trong nó. Điều này đã cho tôi một hộp thoại kích thước bình thường. Khi tôi đặt ConstraintLayout làm gốc mà không thay đổi bất cứ điều gì khác thì chiều rộng hộp thoại được mã hóa thành không rộng lắm!
cắt lá

1

Một trong những giải pháp trước đó gần như đã làm việc. Tôi đã thử một cái gì đó hơi khác nhau và nó đã làm việc cho tôi.

(Hãy chắc chắn rằng bạn nhìn vào giải pháp của anh ấy) Đây là giải pháp của anh ấy .. Bấm vào đây Nó làm việc ngoại trừ: builder.getContext () getTheme () applyStyle (R.style.Theme_Window_NoMinWidth, true);..

Tôi đã đổi nó thành

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

Dòng cuối cùng là những gì khác nhau thực sự.


1

Trong trường hợp của tôi DialogFragmentchiếm kích thước hoạt động đầy đủ như a Fragment. Điều DialogFragmentnày dựa trên bố cục XML, không phải AlertDialog. Lỗi của tôi là thêm đoạn thoại vào FragmentManagernhư một đoạn thông thường:

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

Thay vào đó tôi cần showđoạn thoại:

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

Sau một số chỉnh sửa (tôi có ViewPager2trong bố cục), đoạn hộp thoại trở nên quá hẹp:

nhập mô tả hình ảnh ở đây

Tôi đã sử dụng giải pháp của N1hk :

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

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

Bây giờ nó đã xác định chiều rộng và chiều cao, không phải kích thước hoạt động đầy đủ.

Tôi muốn nói về onCreateViewonCreateDialog. Nếu bạn có một đoạn hộp thoại dựa trên bố cục, bạn có thể sử dụng bất kỳ phương pháp nào trong 2 phương pháp này.

1) Nếu bạn sử dụng onCreateView, thì bạn nên sử dụngonActivityCreated để đặt chiều rộng.

2) Nếu bạn sử dụng onCreateDialogthay vì onCreateView, bạn có thể đặt tham số ở đó. onActivityCreatedsẽ không cần thiết

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
}

Bạn đã lưu ngày của tôi, thiết lập độ rộng trong onActivityCreated làm việc cho tôi.
Hagar Magdy

@HagarMagdy, rất vui khi nghe nó!
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

Đây là giải pháp đơn giản nhất

Giải pháp tốt nhất tôi đã tìm thấy là ghi đè onCreateDialog()thay vì onCreateView(). setContentView () sẽ đặt kích thước cửa sổ chính xác trước khi tăng. Nó loại bỏ nhu cầu lưu trữ / đặt kích thước, màu nền, kiểu, v.v. trong các tệp tài nguyên và đặt chúng theo cách thủ công.

@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

Thêm vào của bạn 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

Điều này sẽ hoạt động hoàn hảo.

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

Đây là khá nhiều những gì câu trả lời được chấp nhận từ hơn 3 năm trước nói.
Adil Hussain

-4

Để có được Hộp thoại bao phủ gần như toàn bộ màn hình: Trước tiên, hãy xác định lớp 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;
    }
}

Sau đó, bạn phải gọi ScreenParamater trước phương thức getDialog.getWindow (). SetLayout () của bạn

@Override
public void onResume()
{
    super.onResume();
    ScreenParameters s = new ScreenParameters();
    getDialog().getWindow().setLayout(s.Width , s.Height);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.