[DialogFragment, Dialog] 안드로이드 DialogFragment 크기 조정하기, 테두리 둥글게 조절하기

2021. 10. 29. 14:49개발/[Kotlin] 안드로이드 개발

반응형

원하는 크기로 띄우고 싶은데 자꾸 에러가 나는 상황 때문에 삽질 기록을 작성합니다..

가끔 Dialog나 DialogFragment를 사용해 Dialog를 띄울 때 내가 원하는 크기로 띄워지지 않는다.

지금까지 그냥 어느정도 dp로 해결을 했었지만 더 자세하게 띄우기 위해 알아보았다.

- 결과물 : 비율로 Dialog 띄우기 !

 

1. FragmeLayout을 사용해 DP값으로 띄우는 방법

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <data>

    </data>

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cstLy"
        android:background="@drawable/border1"
        android:layout_width="250dp"
        android:layout_height="200dp">

        <TextView
            android:id="@+id/txtChoice"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:gravity="center"
            android:text="컵 종류 선택"
            android:textColor="@color/mainColor"
            android:textSize="10sp"
            app:layout_constraintBottom_toTopOf="@id/view"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@id/cstLy" />

        <View
            android:id="@+id/view"
            android:layout_width="match_parent"
            android:layout_height="2dp"
            android:layout_marginTop="5dp"
            android:background="@color/mainColor"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/txtChoice" />

        <TextView
            android:id="@+id/textView11"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            style="@style/BaseTextStyle"
            android:text="QR 인식 완료!\n이제 AI에 컵을 인식해주세요"
            android:textColor="@android:color/black"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/guideline" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.4"
       />
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.8"
            />
        <View
            android:id="@+id/viewType"
            android:layout_width="match_parent"
            android:layout_height="2dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:background="@color/mainColor"
            app:layout_constraintTop_toBottomOf="@id/guideline1" />
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.5"
            />

        <android.widget.Button
            android:id="@+id/btnPaper"
            android:layout_width="0dp"
            android:layout_height="0dp"
            style="@style/BaseTextStyle"
            android:background="@drawable/round_background_subcolor"
            android:textSize="11sp"
            android:text="종이컵"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/guideline2"
            app:layout_constraintTop_toBottomOf="@id/viewType"
            app:layout_constraintStart_toStartOf="parent" />
        <android.widget.Button
            android:id="@+id/btnPlastic"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@android:color/transparent"
            style="@style/BaseTextStyle"
            android:textSize="11sp"
            android:text="플라스틱컵"
            app:layout_constraintStart_toEndOf="@id/guideline2"
            app:layout_constraintTop_toBottomOf="@id/viewType"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            />

    </androidx.constraintlayout.widget.ConstraintLayout>
    </FrameLayout>
</layout>

그냥 말그대로 width와 height의 크기를 dp로 지정해주고 FragmeLayout을 띄우면 된다. 하지만 각 기기별 dpi도 다다르고 내가 원하는 방법과 맞지 않았다.

2. OnStart에서 window값을 dp값으로 지정하는 방법

    override fun onStart() {
        super.onStart()
        dialog?.window?.setLayout(
            resources.getDimensionPixelSize(R.dimen.dimen_popup_width),
            resources.getDimensionPixelSize(R.dimen.dimen_popup_height)
        )
    }

프레임 레이아웃과 마찬가지로 onStart에서 사이즈를 다시 한 번 조정하는 방법. 이것도 마찬가지로 dp값으로 지정되어 내가 원하는 방법이 아니였다.

비율!! 비율로 나타내고 싶은데 

마침내 !!

3. 퍼센트로 나타내는 방법을 알아냈다.

https://ryan94.tistory.com/6 너무 잘 설명해주셔서 참고해도 될 듯 하다.

초보자를 위해 나는 어떻게 사용했는지 설명해보겠다.

BaseDialogFragment.kt

import android.content.Context
import android.graphics.Point
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.DialogFragment

abstract class BaseDialogFragment<VB: ViewDataBinding>(private val layoutId: Int) : DialogFragment() {
    protected lateinit var binding: VB

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        binding = DataBindingUtil.inflate(inflater, layoutId, container, false)
        init()
        return binding.root
    }

    protected open fun init() {

    }
    protected open fun toast(context: Context, msg: String) {
        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
    }
    protected open fun Context.dialogFragmentResize(dialogFragment: DialogFragment, width: Float, height: Float) {
        val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        if (Build.VERSION.SDK_INT < 30) {

            val display = windowManager.defaultDisplay
            val size = Point()

            display.getSize(size)

            val window = dialogFragment.dialog?.window

            val x = (size.x * width).toInt()
            val y = (size.y * height).toInt()
            window?.setLayout(x, y)

        } else {

            val rect = windowManager.currentWindowMetrics.bounds

            val window = dialogFragment.dialog?.window

            val x = (rect.width() * width).toInt()
            val y = (rect.height() * height).toInt()

            window?.setLayout(x, y)
        }
    }
}

먼저 Base코드를 만들어서 dialogFragmentResize를 정의했다. 그리고 !

KindDialog.kt

class KindDialog : BaseDialogFragment<DialogKindBinding>(R.layout.dialog_kind) {

    override fun init() {
        super.init()
        dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
    }

    override fun onResume() {
        super.onResume()
        requireContext().dialogFragmentResize(this@KindDialog, 0.7f, 0.3f)
    }
    
}

onResume() 메소드에서 dialogFragmentResize메소드를 수행한다. 0.7f, 0.3f는 넓이70%, 높이30%의 비율을 말한다.

 

4. 테두리 둥글게 하기

테두리를 둥글게 하기 위해선 역시나 border.xml이 필요하다

res-drawable에 border.xml을 만들어준다.

border.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@android:color/white" />
    <corners android:radius="20dp" />
</shape>

dialog_kind.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <data>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cstLy"
        android:background="@drawable/border1"
        android:layout_width="250dp"
        android:layout_height="200dp">

        <TextView
            android:id="@+id/txtChoice"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:gravity="center"
            android:text="컵 종류 선택"
            android:textColor="@color/mainColor"
            android:textSize="10sp"
            app:layout_constraintBottom_toTopOf="@id/view"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@id/cstLy" />

        <View
            android:id="@+id/view"
            android:layout_width="match_parent"
            android:layout_height="2dp"
            android:layout_marginTop="5dp"
            android:background="@color/mainColor"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@id/txtChoice" />

        <TextView
            android:id="@+id/textView11"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:gravity="center"
            style="@style/BaseTextStyle"
            android:text="QR 인식 완료!\n이제 AI에 컵을 인식해주세요"
            android:textColor="@android:color/black"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/guideline" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.4"
       />
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.8"
            />
        <View
            android:id="@+id/viewType"
            android:layout_width="match_parent"
            android:layout_height="2dp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:background="@color/mainColor"
            app:layout_constraintTop_toBottomOf="@id/guideline1" />
        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/guideline2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintGuide_percent="0.5"
            />

        <android.widget.Button
            android:id="@+id/btnPaper"
            android:layout_width="0dp"
            android:layout_height="0dp"
            style="@style/BaseTextStyle"
            android:background="@drawable/round_background_subcolor"
            android:textSize="11sp"
            android:text="종이컵"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@id/guideline2"
            app:layout_constraintTop_toBottomOf="@id/viewType"
            app:layout_constraintStart_toStartOf="parent" />
        <android.widget.Button
            android:id="@+id/btnPlastic"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@android:color/transparent"
            style="@style/BaseTextStyle"
            android:textSize="11sp"
            android:text="플라스틱컵"
            app:layout_constraintStart_toEndOf="@id/guideline2"
            app:layout_constraintTop_toBottomOf="@id/viewType"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            />

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

코드를 보면 알 수 있듯이 부모 레이아웃에 background로 박으면..!!!

마지막으로..

KindDialog.kt

class KindDialog : BaseDialogFragment<DialogKindBinding>(R.layout.dialog_kind) {

    override fun init() {
        super.init()
        dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
        dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
    }

    override fun onResume() {
        super.onResume()
        requireContext().dialogFragmentResize(this@KindDialog, 0.7f, 0.3f)
    }

}

onCreateView에 dialog 윈도우의 배경과 타이틀을 수정해주면 성공이다.

주의해야할점

- 모든 dialog의 크기나 윈도우를 조정하는 건 setContentView 이후에 행해져야 합니다.

- DialogFragment는 JetPack navigation을 사용해 findNavController로 다음 화면을 이동하는 방식을 사용하면 

적용이 안되더라. 아마 navigation이 프래그먼트로 착각(?)하고 전체화면으로 고정 되는거 같은데.. 

아시는 분 계시면 댓글 부탁 드리겠습니다.

KindDialog().show(requireActivity().supportFragmentManager,"dd")로 띄우면 된다 ~

 

 

반응형