web-dev-qa-db-ja.com

DialogFragmentの幅と高さを設定するには?

DialogFragmentのレイアウトをxmlレイアウトファイルで指定し(layout_mydialogfragment.xmlと呼びましょう)、特にそのlayout_widthおよびlayout_height属性を指定します(それぞれ100dpとしましょう)。次に、DialogFragmentのonCreateView(...)メソッドでこのレイアウトを次のように拡張します。

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

残念ながら、ダイアログ(DialogFragment)が表示されると、xmlレイアウトファイルで指定されているlayout_widthおよびlayout_heightを尊重しません(そして、コンテンツに応じてダイアログが縮小または拡大します)。 xmlレイアウトファイルで指定されているlayout_widthlayout_heightを尊重するようにダイアログを取得できるかどうか、またはどのように取得できるかは誰でも知っていますか?現時点では、DialogFragmentのonResume()メソッドでダイアログの幅と高さを次のように再度指定する必要があります...

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

...したがって、望ましくないことに、ダイアログの幅と高さを今後2か所変更する必要があります。

143
Adil Hussain

リソース値から直接変換する場合:

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

次に、ダイアログのレイアウトでmatch_parentを指定します。

Android:layout_width="match_parent"
Android:layout_height="match_parent"

心配する必要があるのは1か所だけです(DialogFragment#onResumeに配置します)。完全ではありませんが、少なくとも、ダイアログのレイアウトファイルのルートとしてRelativeLayoutを使用する場合には機能します。

146
Blix247

最終的にFragment.onResume()をオーバーライドし、基になるダイアログから属性を取得し、そこで幅/高さのパラメーターを設定しました。一番外側のレイアウトの高さ/幅をmatch_parentに設定します。このコードは、xmlレイアウトで定義したマージンも尊重しているようです。

@Override
public void onResume() {
    super.onResume();
    ViewGroup.LayoutParams params = getDialog().getWindow().getAttributes();
    params.width = LayoutParams.MATCH_PARENT;
    params.height = LayoutParams.MATCH_PARENT;
    getDialog().getWindow().setAttributes((Android.view.WindowManager.LayoutParams) params);
}
116
jmaculate

XMLメインレイアウト(私の場合はLinearLayout)で以下を定義する固定サイズのDialogFragmentを取得しました。

Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:minWidth="1000dp"
Android:minHeight="450dp"
90
Jose_GD

私の場合に働いた唯一のことは、ここで指摘された解決策でした: http://adilatwork.blogspot.mx/2012/11/Android-dialogfragment-dialog-sizing.html

Adilブログ投稿のスニペット:

@Override
public void onStart()
{
  super.onStart();

  // safety check
  if (getDialog() == null)
    return;

  int dialogWidth = ... // specify a value here
  int dialogHeight = ... // specify a value here

  getDialog().getWindow().setLayout(dialogWidth, dialogHeight);

  // ... other stuff you want to do in your onStart() method
}
50
Rodrigo

DialogFragmentの幅と高さを制御する1つの方法は、値がWRAP_CONTENTの場合、ダイアログがビューの幅と高さを尊重するようにすることです。

ThemeOverlay.AppCompat.Dialogを使用する

これを実現する簡単な方法の1つは、Androidサポートライブラリに含まれているThemeOverlay.AppCompat.Dialogスタイルを使用することです。

DialogFragment with 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 with AlertDialog(注意:minHeight="48dp"):

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_AppCompat_Dialog);
    builder.setView(view);
    return builder.create();
}

ダイアログを作成するときに、アプリのxmlテーマに追加することで、ThemeOverlay.AppCompat.Dialogをデフォルトのテーマとして設定することもできます。
多くのダイアログでは見栄えを良くするためにデフォルトの最小幅が必要なので注意してください。

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

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

DialogFragmentAlertDialogAndroid:alertDialogThemeまたはalertDialogThemeを使用(注意:minHeight="48dp"):

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
    builder.setView(view);
    return builder.create();
}

ボーナス

古いAndroid AP​​Iでは、Dialogsにはタイトルが設定されていなくても、幅の問題があるようです。
ThemeOverlay.AppCompat.Dialogスタイルを使用したくない場合で、Dialogにタイトルが必要ない(またはカスタムのタイトルがある)場合は、無効にすることができます。

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = LayoutInflater.from(getContext());
    View view = inflater.inflate(R.layout.dialog_view, null);

    Dialog dialog = new Dialog(getContext());
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setContentView(view);
    return dialog;
}

時代遅れの回答、ほとんどの場合機能しません

プログラムで固定サイズを指定せずに、ダイアログがレイアウトの幅と高さを尊重するようにしました。

Android:windowMinWidthMinorAndroid:windowMinWidthMajorが問題を引き起こしていると考えました。 ActivityまたはDialogのテーマには含まれていませんでしたが、それらはまだActivityテーマに適用されていました。

私は3つの可能な解決策を思いつきました。

解決策1:カスタムダイアログテーマを作成し、DialogFragmentでダイアログを作成するときに使用します。

<style name="Theme.Material.Light.Dialog.NoMinWidth" parent="Android:Theme.Material.Light.Dialog">
    <item name="Android:windowMinWidthMinor">0dip</item>
    <item name="Android:windowMinWidthMajor">0dip</item>
</style>
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new Dialog(getActivity(), R.style.Theme_Material_Light_Dialog_NoMinWidth);
}

解決策2:ダイアログのContextThemeWrapperとして機能するContextで使用されるカスタムテーマを作成します。カスタムダイアログテーマを作成しない場合(たとえば、Android:dialogThemeで指定されたテーマを使用する場合)に使用します。

<style name="Theme.Window.NoMinWidth" parent="">
    <item name="Android:windowMinWidthMinor">0dip</item>
    <item name="Android:windowMinWidthMajor">0dip</item>
</style>
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    return new Dialog(new ContextThemeWrapper(getActivity(), R.style.Theme_Window_NoMinWidth), getTheme());
}

ソリューション3(AlertDialogを使用):Android:windowMinWidthMinorおよびAndroid:windowMinWidthMajorAlertDialog$Builderによって作成されたContextThemeWrapperに適用します。

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

落とし穴#13:DialogFragmentレイアウト

それは本当に麻痺しているようなものです。

DialogFragmentを作成するときに、onCreateView(.xmlレイアウトをアタッチするためにViewGroupを渡す)またはonCreateDialogをオーバーライドすることを選択できます。

両方のメソッドをオーバーライドしないでください。ダイアログのレイアウトがいつ膨らんだか、または膨らんだかどうかについてAndroidを混同する可能性が非常に高いからです。 WTF?

OnCreateDialogまたはOnCreateViewをオーバーライドするかどうかの選択は、ダイアログの使用方法によって異なります。

  • ウィンドウでダイアログを起動する場合(通常の動作)、OnCreateDialogをオーバーライドすることが期待されます。
  • 既存のUIレイアウト内にダイアログフラグメントを埋め込む場合(あまり一般的ではない)、OnCreateViewをオーバーライドする必要があります。

これはおそらく世界で最悪のことです。

onCreateDialog狂気

したがって、onCreateDialog内のDialogFragmentをオーバーライドして、ウィンドウに表示するAlertDialogのカスタマイズされたインスタンスを作成します。クール。ただし、onCreateDialogは、カスタム.xmlレイアウトtoを添付するViewGroupを受け取らないことに注意してください。問題ありません。単にnullinflateメソッドに渡すだけです。

狂気を始めましょう。

onCreateDialogをオーバーライドすると、Android COMPLETELY IGNORES展開する.xmlレイアウトのルートノードのいくつかの属性。これには以下が含まれますが、おそらくこれに限定されません:

  • background_color
  • layout_gravity
  • layout_width
  • layout_height

これはほとんど滑comicです。すべての.xmlレイアウトのlayout_widthおよびlayout_heightを設定する必要があるか、Android St​​udioが恥ずかしい素敵な小さな赤いバッジであなたを平手打ちします。

WordDialogFragmentだけで私はukeりたくなる。 Androidの落とし穴とスナフスで満たされた小説を書くこともできますが、これは最も内部的なものの1つです。

正気に戻るには、まず、期待するbackground_colorlayout_gravityを復元するスタイルを宣言します。

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

上記のスタイルは、Dialogsのベーステーマ(この例ではAppCompatテーマ)から継承します。

次に、スタイルをプログラムで適用して、単に捨てられた値Androidを元に戻し、標準のAlertDialogのルックアンドフィールを復元します。

public class MyDialog extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        View layout = getActivity().getLayoutInflater().inflate(R.layout.my_dialog_layout, null, false);
        assert layout != null;
        //build the alert dialog child of this fragment
        AlertDialog.Builder b = new AlertDialog.Builder(getActivity());
        //restore the background_color and layout_gravity that Android strips
        b.getContext().getTheme().applyStyle(R.style.MyAlertDialog, true);
        b.setView(layout);
        return b.create();
    }
}

上記のコードはAlertDialogを再びAlertDialogのように見せます。たぶんこれで十分でしょう。

しかし、待ってください、まだあります!

表示されているときにAlertDialogSPECIFIClayout_widthまたはlayout_heightを設定することを検討している場合(可能性が高い)、何をしたかはまだわかりません!

ファンシーな新しいスタイルで特定のlayout_widthまたはlayout_heightを設定しようとすると、Androidもそれを完全に無視することに気づいたとき、喜びは続きます!:

<style name="MyAlertDialog" parent="Theme.AppCompat.Dialog">
    <item name="Android:windowBackground">@Android:color/transparent</item>
    <item name="Android:layout_gravity">center</item>
    <!-- NOPE!!!!! --->
    <item name="Android:layout_width">200dp</item>
    <!-- NOPE!!!!! --->
    <item name="Android:layout_height">200dp</item>
</style>

SPECIFICウィンドウの幅または高さを設定するには、 'nutherメソッド全体に進み、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);
}

多くの人は、WindowManager.LayoutParamsをより一般的なViewGroup.LayoutParamsにキャストするというAndroidの悪い例に従っていますが、数回後にViewGroup.LayoutParamsWindowManager.LayoutParamsに戻すだけです。効果的なJavaは、コードを解読するのをさらに難しくする以外に、不必要なキャストが何も提供しないことを気にかけられます。

サイドノート:Android SDK全体でLayoutParamsが20回繰り返されています-根本的に貧弱なデザインの完璧な例です。

要約すれば

DialogFragmentをオーバーライドするonCreateDialogsの場合:

  • 標準のAlertDialogルックアンドフィールを復元するには、background_color = transparentおよびlayout_gravity = centerを設定するスタイルを作成し、そのスタイルをonCreateDialogに適用します。
  • 特定のlayout_widthおよび/またはlayout_heightを設定するには、プログラムでonResumeLayoutParamsに設定します
  • 健全性を維持するために、Android SDKについて考えないようにしてください。
30
rmirabelle

DialogFragmentを少し広くする必要がある場合、minWidthを設定します。

<LinearLayout
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:minWidth="320dp"
    ... />
13
Andrey

一番外側のレイアウトの寸法は、ダイアログでは機能しません。寸法を最も外側に設定するレイアウトを追加できます。

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

以下は、xmlでDialogFragmentの幅/高さを設定する方法です。 viewHierarchyを透明な背景を持つFramelayout(任意のレイアウトが機能します)でラップするだけです。

透明な背景は特別なフラグのようです。これを行うと、frameLayoutの子がウィンドウの中央に自動的に配置されるためです。フラグメントの背後にある全画面が暗くなり、フラグメントがアクティブな要素であることを示します。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:background="@color/transparent">

    <RelativeLayout
        Android:layout_width="match_parent"
        Android:layout_height="300dp"
        Android:background="@color/background_material_light">

      .....
5
NameSpace

ルート要素のレイアウトパラメーターの設定を修正しました。

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

onResumeonStart内のWindowの幅と高さを設定するためにDialogFragmentまたはDialogをオーバーライドする説得力のある理由はありません-これらの特定のライフサイクルメソッドは繰り返し呼び出され、マルチウィンドウなどの理由でコードを複数回不必要に実行する可能性があります切り替え、バックグラウンド化、アプリのフォアグラウンド化など。その繰り返しの結果はかなり些細なことですが、なぜそれで落ち着くのでしょうか?

オーバーライドされたonActivityCreated()メソッド内で代わりにwidth/heightを設定すると、このメソッドは実際にはDialogFragmentのインスタンスごとに1回しか呼び出されないため、改善されます。例えば:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    Window window = getDialog().getWindow();
    assert window != null;

    WindowManager.LayoutParams layoutParams = window.getAttributes();
    layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
    window.setAttributes(layoutParams);
}

上記では、デバイスの向きに関係なく、幅をmatch_parentに設定しています。ランドスケープダイアログをそれほど広くしたくない場合は、事前にgetResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAITかどうかを確認できます。

3
N1hk

幅にパーセンテージを使用できます。

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

この例では、Holoテーマを使用しました。

3
StefanoM5

以下のコードで、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();
3
Ruchit Mittal

AlertDialog.Builderを使用してダイアログを作成するため、OnShowListener内でRodrigoの回答を使用しました。

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

        });
2
Jorge Garcia

Android 6.0で作業中に、同じ問題が発生しました。 AlertDialogは、カスタムビューのルートwidthに設定されている実際のwidthに関係なく、テーマに設定されている事前定義済みLayoutにデフォルト設定されます。 loading_messagewidthTextViewを適切に調整して設定することができました。さらに調査することなく、実際の要素のサイズを決定し、ルートLayoutでそれらをラップすると、期待どおりに動作するようです。以下は、ダイアログのwidthを正しく設定する読み込みダイアログのXMLレイアウトです。アニメーションに このライブラリ を使用します。

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

カスタムダイアログレイアウトの親レイアウトをRelativeLayoutに設定し、共通の幅と高さを自動的に取得します。

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

簡単で堅牢:

@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
SANAL CAMBAZ

これは最も簡単なソリューションです

私が見つけた最良の解決策は、onCreateDialog()ではなくonCreateView()をオーバーライドすることです。 setContentView()は、膨張する前に正しいウィンドウサイズを設定します。リソースファイルに寸法、背景色、スタイルなどを保存/設定し、手動で設定する必要がなくなります。

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    Dialog dialog = new Dialog(getActivity());
    dialog.setContentView(R.layout.fragment_dialog);

    Button button = (Button) dialog.findViewById(R.id.dialog_button);
    // ...
    return dialog;
}
1
parkgrrr

私の場合、RelativeLayout内のビューに与えられたalign_parentBottom="true"が原因でした。すべてのalignParentBottomを削除し、すべてのレイアウトを垂直のLinearLayoutsに変更し、問題はなくなりました。

1
mehmet6parmak

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

以前のソリューションの1つはほとんど機能しました。私は少し違うことを試してみましたが、それは私のために働いてしまいました。

(必ず彼のソリューションを見てください)これは彼のソリューションでした.. ここをクリック 次を除いて機能しました:builder.getContext()。getTheme()。applyStyle(R.style.Theme_Window_NoMinWidth、 true);

に変更しました

 @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {


        // Use the Builder class for convenient dialog construction
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

        // Get layout inflater
        LayoutInflater layoutInflater = getActivity().getLayoutInflater();

        // Set layout by setting view that is returned from inflating the XML layout
        builder.setView(layoutInflater.inflate(R.layout.dialog_window_layout, null));


        AlertDialog dialog = builder.create();

        dialog.getContext().setTheme(R.style.Theme_Window_NoMinWidth);

最後の行は、本当に違うものです。

0
TheAppFoundry