[Android ๊ธฐ์ดˆ] 13. ๋‹ค์ด์–ผ๋กœ๊ทธ (Dialog)
๋ฐ˜์‘ํ˜•

 

 

 

 

 

 

 

๋Œ€ํ™”์ƒ์ž  |  Views  |  Android Developers

์ด ํŽ˜์ด์ง€๋Š” Cloud Translation API๋ฅผ ํ†ตํ•ด ๋ฒˆ์—ญ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋Œ€ํ™”์ƒ์ž ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด ์ •๋ฆฌํ•˜๊ธฐ ๋‚ด ํ™˜๊ฒฝ์„ค์ •์„ ๊ธฐ์ค€์œผ๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ์ €์žฅํ•˜๊ณ  ๋ถ„๋ฅ˜ํ•˜์„ธ์š”. Compose ๋ฐฉ๋ฒ• ์‚ฌ์šฉํ•ด ๋ณด๊ธฐ Jetpack Compose๋Š” Android

developer.android.com

 

 

 

 

1. ๋‹ค์ด์–ผ๋กœ๊ทธ (Dialog, ๋Œ€ํ™”์ƒ์ž)

 

 

  • ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ฒฐ์ •์„ ๋‚ด๋ฆฌ๊ฑฐ๋‚˜ ์ถ”๊ฐ€์ •๋ณด๋ฅผ ์ž…๋ ฅํ•˜๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•˜๋Š” ์ž‘์€ ์ฐฝ
  • ํ™”๋ฉด์„ ๊ฐ€๋“ ์ฑ„์šฐ์ง€ ์•Š์œผ๋ฉฐ ๋ณดํ†ต์€ ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค์Œ์œผ๋กœ ๊ณ„์† ์ง„ํ–‰ํ•˜๊ธฐ ์ „์— ์กฐ์น˜๋ฅผ ์ทจํ•ด์•ผ ํ•˜๋Š” ๋ชจ๋‹ฌ ์ด๋ฒคํŠธ์— ์‚ฌ์šฉ

 

 

 

 

2. ๋‹ค์ด์–ผ๋กœ๊ทธ ๊ตฌ์กฐ

  • AlertDialogํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋Œ€ํ™” ์ƒ์ž ๋””์ž์ธ์„ ๋นŒ๋“œ ๊ฐ€๋Šฅ
  • ๋Œ€๊ฐœ ์ด ๋‹ค์ด์–ผ๋กœ๊ทธ ํด๋ž˜์Šค๋งŒ ์žˆ์œผ๋ฉด ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ


1. ์ œ๋ชฉ (์„ ํƒ)

  • ์„ ํƒ ์‚ฌํ•ญ (๋‹จ์ˆœํ•œ ๋ฉ”์‹œ์ง€ ๋˜๋Š” ์งˆ๋ฌธ์„ ๋‚˜ํƒ€๋‚ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์—†์–ด๋„ ๋จ)
  • ์ฝ˜ํ…์ธ  ์˜์—ญ์— ์ƒ์„ธํ•œ ๋ฉ”์‹œ์ง€,๋ชฉ๋ก ๋˜๋Š” ๋งž์ถค ๋ ˆ์ด์•„์›ƒ์ด ์ฑ„์›Œ์ ธ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉ

 

2. ์ฝ˜ํ…์ธ  ์˜์—ญ 

  • ๋ฉ”์‹œ์ง€, ๋ชฉ๋ก ๋˜๋Š” ๋‹ค๋ฅธ ๋งž์ถค ๋ ˆ์ด์•„์›ƒ์„ ํ‘œ์‹œ ํ•  ์ˆ˜ ์žˆ์Œ

 

3. ์ž‘์—… ๋ฒ„ํŠผ

  • ๋Œ€ํ™” ์ƒ์ž ํ•˜๋‚˜์— ์ž‘์—… ๋ฒ„ํŠผ์ด ์„ธ ๊ฐœ๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด ์•ˆ ๋จ

 

 

 

3. ๋‹ค์ด์–ผ๋กœ๊ทธ ์˜ˆ์ œ

 

3-1. ๊ธฐ๋ณธ ๋‹ค์ด์–ผ๋กœ๊ทธ

// 1. ๊ธฐ๋ณธ ๋‹ค์ด์–ผ๋กœ๊ทธ
        binding.btn1Alert.setOnClickListener {
            var builder = AlertDialog.Builder(this)
            builder.setTitle("๊ธฐ๋ณธ ๋‹ค์ด์–ผ๋กœ๊ทธ ํƒ€์ดํ‹€")
            builder.setMessage("๊ธฐ๋ณธ ๋‹ค์ด์–ผ๋กœ๊ทธ ๋ฉ”์„ธ์ง€")
            builder.setIcon(R.mipmap.ic_launcher)

            // ๋ฒ„ํŠผ ํด๋ฆญ์‹œ์— ๋ฌด์Šจ ์ž‘์—…์„ ํ•  ๊ฒƒ์ธ๊ฐ€!
            val listener = object : DialogInterface.OnClickListener {
                override fun onClick(p0: DialogInterface?, p1: Int) {
                    when (p1) {
                        DialogInterface.BUTTON_POSITIVE ->
                            binding.tvTitle.text = "BUTTON_POSITIVE"
                        DialogInterface.BUTTON_NEUTRAL ->
                            binding.tvTitle.text = "BUTTON_NEUTRAL"
                        DialogInterface.BUTTON_NEGATIVE ->
                            binding.tvTitle.text = "BUTTON_NEGATIVE"
                    }
                }
            }

            builder.setPositiveButton("Positive", listener)
            builder.setNegativeButton("Negative", listener)
            builder.setNeutralButton("Neutral", listener)

            builder.show()
        }

 

 

 

3-2. ์ปค์Šคํ…€ ๋‹ค์ด์–ผ๋กœ๊ทธ

         binding.btn2Custom.setOnClickListener {
            val builder = AlertDialog.Builder(this)
            builder.setTitle("์ปค์Šคํ…€ ๋‹ค์ด์–ผ๋กœ๊ทธ")
            builder.setIcon(R.mipmap.ic_launcher)

            val v1 = layoutInflater.inflate(R.layout.dialog, null)
            builder.setView(v1)

            // p0์— ํ•ด๋‹น AlertDialog๊ฐ€ ๋“ค์–ด์˜จ๋‹ค. findViewById๋ฅผ ํ†ตํ•ด view๋ฅผ ๊ฐ€์ ธ์™€์„œ ์‚ฌ์šฉ
            val listener = DialogInterface.OnClickListener { p0, p1 ->
                val alert = p0 as AlertDialog
                val edit1: EditText? = alert.findViewById<EditText>(R.id.editText)
                val edit2: EditText? = alert.findViewById<EditText>(R.id.editText2)

                binding.tvTitle.text = "์ด๋ฆ„ : ${edit1?.text}"
                binding.tvTitle.append(" / ๋‚˜์ด : ${edit2?.text}")
            }

            builder.setPositiveButton("ํ™•์ธ", listener)
            builder.setNegativeButton("์ทจ์†Œ", null)

            builder.show()
        }
dialog.xml ์ถ”๊ฐ€

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:orientation="vertical">

        <EditText
            android:id="@+id/editText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPersonName"
            android:text="Name" />

        <EditText
            android:id="@+id/editText2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="textPersonName"
            android:text="AGE" />
    </LinearLayout>
</LinearLayout>

 

 

 

3-3. ๋‚ ์งœ ๋‹ค์ด์–ผ๋กœ๊ทธ (DatePicker Dialog)

        binding.btn3Date.setOnClickListener {
            val calendar = Calendar.getInstance()
            val year = calendar.get(Calendar.YEAR)
            val month = calendar.get(Calendar.MONTH)
            val day = calendar.get(Calendar.DAY_OF_MONTH)

            val listener = DatePickerDialog.OnDateSetListener { datePicker, i, i2, i3 ->
                // i๋…„ i2์›” i3์ผ
                binding.tvTitle.text = "${i}๋…„ ${i2 + 1}์›” ${i3}์ผ"
            }

            var picker = DatePickerDialog(this, listener, year, month, day)
            picker.show()
        }

 

 

3-4. ์‹œ๊ฐ„ ๋‹ค์ด์–ผ๋กœ๊ทธ (TimePicker Dialog)

        binding.btn4Time.setOnClickListener {
            val calendar = Calendar.getInstance()
            val hour = calendar.get(Calendar.HOUR)
            val minute = calendar.get(Calendar.MINUTE)

            val listener = TimePickerDialog.OnTimeSetListener { timePicker, i, i2 ->
                binding.tvTitle.text = "${i}์‹œ ${i2}๋ถ„"
            }

            val picker = TimePickerDialog(this, listener, hour, minute, false) // trueํ•˜๋ฉด 24์‹œ๊ฐ„ ์ œ
            picker.show()
        }

 

 

3-5. ์ง„ํ–‰ ๋‹ค์ด์–ผ๋กœ๊ทธ (Progress Dialog)

 

        binding.btn5Porgress.setOnClickListener {
            // ๊ถŒ์žฅํ•˜์ง„ ์•Š์ง€๋งŒ ์‚ฌ์šฉ์€ ๊ฐ€๋Šฅํ•˜๋‹ค.
            pro = ProgressDialog.show(this, "ํƒ€์ดํ‹€์ž…๋‹ˆ๋‹ค.", "๋ฉ”์‹œ์ง€์ž…๋‹ˆ๋‹ค.")

            // ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ†ตํ•ด์„œ ์ข…๋ฃŒ ์ž‘์—…์„ ํ•œ๋‹ค.
            val handler = Handler()
            val thread = Runnable { pro?.cancel() }
            handler.postDelayed(thread, 5000) // ๋”œ๋ ˆ์ด๋Š” 5์ดˆ
        }


ํ”„๋กœ๊ทธ๋ž˜์Šค ๋‹ค์ด์–ผ๋กœ๊ทธ ๋‹ค๋ฅธ ๋ฐฉ์‹ : (์ปค์Šคํ…€๊ณผ ๋น„์Šท)
binding.btn5Porgress.setOnClickListener {
            val builder = AlertDialog.Builder(this)
            builder.setTitle("ํ”„๋กœ๊ทธ๋ž˜์Šค๋ฐ”")
            builder.setIcon(R.mipmap.ic_launcher)

            val v1 = layoutInflater.inflate(R.layout.progressbar, null)
            builder.setView(v1)

            builder.show()
        }
progressbar.xml

<?xml version="1.0" encoding="utf-8"?>
<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">

    <ProgressBar
        android:id="@+id/progressbar"
        android:layout_width="match_parent"
        android:layout_height="76dp"
        android:layout_gravity="center"
        android:layout_marginTop="48dp"
        android:indeterminate="false"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="loading..."
        android:textSize="16sp"
        android:layout_marginTop="16dp"/>
</LinearLayout>

 

 

 

4. DialogFragment

  • DialogFragment๋Š” ์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ๋Œ€ํ™”์ƒ์ž ํ˜•ํƒœ์˜ UI๋ฅผ ๊ตฌํ˜„ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํด๋ž˜์Šค
  • Fragment ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉด์„œ, ์ถ”๊ฐ€๋กœ ๋Œ€ํ™”์ƒ์ž๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ–๊ณ  ์žˆ์Œ
  • DialogFragment๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋Œ€ํ™”์ƒ์ž์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋ฅผ ๋”์šฑ ์„ธ๋ฐ€ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ,
    ํ™”๋ฉด ํšŒ์ „ ๊ฐ™์€ ๊ตฌ์„ฑ ๋ณ€๊ฒฝ ์‹œ์—๋„ ๋Œ€ํ™”์ƒ์ž์˜ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Œ
  • DialogFragment์˜ ์—ฌ๋Ÿฌ ์šฉ๋„
      - ์ „ํ†ต์ ์ธ ๋Œ€ํ™”์ƒ์ž
      - ๋ถ€๋ชจ ์•กํ‹ฐ๋น„ํ‹ฐ์˜ ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ ์‹คํ–‰๋˜๋Š” ๋‚ด์žฅ๋œ ํ”„๋ž˜๊ทธ๋จผํŠธ
      - ๋Œ€ํ™”์ƒ์ž์™€ ์œ ์‚ฌํ•œ UI๋ฅผ ๊ฐ€์ง„ ์ „์ฒด ํ™”๋ฉด ํ”„๋ž˜๊ทธ๋จผํŠธ
  • ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ฒฐ์ •์„ ์š”๊ตฌํ•˜๊ฑฐ๋‚˜, ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ์ž…๋ ฅ๋ฐ›๊ฑฐ๋‚˜, ์•Œ๋ฆผ์„ ์ œ๊ณตํ•˜๋Š” ๋“ฑ์— ์‚ฌ์šฉ๋จ

 

MainActivity.kt
๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด MyDialogFragment๋ฅผ ํ‘œ์‹œ
show ๋ฉ”์„œ๋“œ๋Š” FragmentManager์™€ ๋Œ€ํ™”์ƒ์ž์˜ ํƒœ๊ทธ๋ฅผ ์ธ์ž๋กœ ๋ฐ›์Œ


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Show the dialog by calling show() method
        findViewById<Button>(R.id.showDialogButton).setOnClickListener {
            MyDialogFragment().show(supportFragmentManager, "MyDialogFragment")
        }
    }
}
MyDialogFragment.kt
onCreateDialog ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•˜์—ฌ AlertDialog๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ตฌ์„ฑ
๋Œ€ํ™”์ƒ์ž์—๋Š” ๋ฉ”์‹œ์ง€์™€ ๋‘ ๊ฐœ์˜ ๋ฒ„ํŠผ("Yes"์™€ "No")์ด ์žˆ์œผ๋ฉฐ, 
๊ฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ์˜ ๋™์ž‘์€ ์ด ์˜ˆ์ œ์—์„œ๋Š” ์ •์˜๋˜์ง€ ์•Š์Œ


class MyDialogFragment : DialogFragment() {

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return activity?.let {
            // Use the Builder class for convenient dialog construction
            val builder = AlertDialog.Builder(it)
            builder.setMessage("Do you like this app?")
                .setPositiveButton("Yes") { dialog, id ->
                    // Send the positive button event back to the host activity
                }
                .setNegativeButton("No") { dialog, id ->
                    // Send the negative button event back to the host activity
                }
            // Create the AlertDialog object and return it
            builder.create()
        } ?: throw IllegalStateException("Activity cannot be null")
    }
}

 

 

 

 

 

 

๋ฐ˜์‘ํ˜•
 ๐Ÿ’ฌ C O M M E N T