Help us understand the problem. What is going on with this article?

DialogFragmentの大きさを自由に変えたい

背景

ダイアログは基本小さめの画面なことが多いが、カスタムUIでフルスクリーンで表示したり画面比率何%で表示したり自在に操りたいなと思ったので実装してみた備忘録です

・androidX環境
・色々なサイズで使いたい
・xmlはConstraintLayoutで中身を書きたい

stackoverflowはじめ古い記事を見ていると、ParentをRelativeLayoutやLineaLayoutにしようとか、Styleを定義しようと書かれていましたがこちらが簡単かな?と思ったので書くことにします

フルスクリーン

実装

FullScreenDialogFragment.kt
package com.example.coroutines

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.DialogFragment
import kotlinx.android.synthetic.main.view_full_screen_dialog.view.*

class FullScreenDialogFragment : DialogFragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.view_full_screen_dialog, container, false).apply {
            text.setOnClickListener {
                Toast.makeText(it.context, text.text, Toast.LENGTH_SHORT).show()
            }

            close.setOnClickListener {
                dismiss()
            }
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        dialog?.setCancelable(true)
    }

    override fun onStart() {
        super.onStart()
        dialog?.window?.setBackgroundDrawable(null)
        dialog?.window?.setLayout(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
    }

    companion object {
        fun newInstance() = FullScreenDialogFragment()
    }
}
view_full_screen_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">

    <TextView
        android:id="@+id/close"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_marginTop="24dp"
        android:layout_marginEnd="24dp"
        android:drawableLeft="@drawable/ic_close_24"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="RtlHardcoded" />

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="TEXT"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

肝なのはActivityに関連するonStartsetBackGroundDrawable/setLayoutwindowに対してサイズを決めてしまうということ

なぜxmlでmatch_parentとか適当にXXXdpとか設定してもうまくいかないのは、あくまでDialogFragmentはDialogのwrapperにすぎないので、サイズ調整するのはcontainerではなくwindowで行う必要があるということですね。

DialogFragmentのスタイルを設定するDialogFragment#setTyleでもこのような記述があります。

The same effect can be achieve by manually setting Dialog and Window attributes yourself. Calling this after the fragment's Dialog is created will have no effect.

DialogFragment.java
    /**
     * Call to customize the basic appearance and behavior of the
     * fragment's dialog.  This can be used for some common dialog behaviors,
     * taking care of selecting flags, theme, and other options for you.  The
     * same effect can be achieve by manually setting Dialog and Window
     * attributes yourself.  Calling this after the fragment's Dialog is
     * created will have no effect.
     *
     * @param style Selects a standard style: may be {@link #STYLE_NORMAL},
     * {@link #STYLE_NO_TITLE}, {@link #STYLE_NO_FRAME}, or
     * {@link #STYLE_NO_INPUT}.
     * @param theme Optional custom theme.  If 0, an appropriate theme (based
     * on the style) will be selected for you.
     */
    public void setStyle(@DialogStyle int style, @StyleRes int theme) {
        mStyle = style;
        if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) {
            mTheme = android.R.style.Theme_Panel;
        }
        if (theme != 0) {
            mTheme = theme;
        }
    }

サイズ指定

上記も踏まえてとあるサイズを指定したい場合は以下のようになります

snippet.kt
override fun onStart() {
    super.onStart()
    dialog?.window?.setBackgroundDrawable(null)
    val width = (resources.displayMetrics.widthPixels * 0.95).toInt()
    val height = (resources.displayMetrics.heightPixels * 0.95).toInt()
    dialog?.window?.setLayout(width, height)
}

setLayoutにはwidth, heightで指定できるので各々好きなサイズで実装ができます

まとめ

・onStartにサイズの記載をしよう
・xmlでParentViewのサイズをコントロールしてもうまくはいかない

間違い等ありましたら遠慮なく指摘していただけると幸いです

sudo5in5k
しがないAndroiderやってまうs
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away