Edited at

ディスプレイ全体に DialogFragment を表示する方法(修正版)

More than 1 year has passed since last update.


前提

以下のレイアウトを元に DialogFragment を全画面表示に変更していきます。


view_dialog.xml

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ボタン①" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ボタン②" />
</LinearLayout>

</LinearLayout>


以下は ActivityDialogFragment を表示するコードです。


MainActivity.java

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// DialogFragment を表示します
ExampleDialogFragment exampleDialogFragment = new ExampleDialogFragment();
exampleDialogFragment.show(getSupportFragmentManager(),
ExampleDialogFragment.class.getSimpleName());
}
}



:one: DialogFragment を普通に表示する

view_dialog.xmlLinearLayoutmatch_parent

を指定しているにも関わらず、縦横共に余白が残っています。


ExampleDialogFragment.java

import android.app.Dialog;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;

public class ExampleDialogFragment extends DialogFragment {

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

return dialog;
}
}


Screenshot_2015-01-03-07-56-05.png


:two: Dialog の枠を残したまま全画面表示にする


ExampleDialogFragment.java

import android.app.Dialog;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.view.ViewGroup;

public class ExampleDialogFragment extends DialogFragment {

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(getActivity());
dialog.setContentView(R.layout.view_dialog);
// DialogFragment のレイアウトを縦横共に全域まで広げます
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);

return dialog;
}
}


Screenshot_2015-01-03-07-57-00.png


:three: Dialog の枠を無くした状態で全画面表示にする


ExampleDialogFragment.java

import android.app.Dialog;

import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.view.ViewGroup;
import android.view.Window;

public class ExampleDialogFragment extends DialogFragment {

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = new Dialog(getActivity());
// DialogFragment をタイトル無しにします
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.view_dialog);
// 背景を透明にします
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);

return dialog;
}
}


Screenshot_2015-01-03-07-57-27.png


:four: 背景の薄暗さを消す

values/styles.xml に以下を追記して、薄暗さ(Dim)の値を0に設定します。


values/styles.xml

<style name="NoDimDialogFragmentStyle" parent="@android:style/Theme.Holo.Light.Dialog">

<item name="android:backgroundDimAmount">0.0</item>
<item name="android:backgroundDimEnabled">false</item>
</style>


ExampleDialogFragment.java

import android.app.Dialog;

import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.view.ViewGroup;
import android.view.Window;

public class ExampleDialogFragment extends DialogFragment {

@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// ここで薄暗さ0のスタイルを設定します
Dialog dialog = new Dialog(getActivity(), R.style.NoDimDialogFragmentStyle);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.view_dialog);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);

return dialog;
}
}


Screenshot_2015-01-03-08-04-14.png


:information_source: 補足


何故 DialogFragment を使うのか


AlertDialog だと

ActivityAlertDialog を表示した後に画面を回転すると、AlertDialog が消え去り logcatE/WindowManager: android.view.WindowLeaked エラーが表示されます :sob:


MainActivity.java

import android.os.Bundle;

import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new AlertDialog.Builder(MainActivity.this)
.setTitle("タイトル")
.setMessage("メッセージ")
.setPositiveButton("OK", null)
.show();
}
});
}
}


図1. 画面回転前
図2. 画面回転後

Screenshot_1507533549.png
Screenshot_1507533552.png


DialogFragment であれば

画面を回転しても表示状態が保持され、リークも発生しません :ok_woman: