📱
Android:DialogFragmentからDialogFragmentを呼び出す方法
はじめに
DialogFragmentをつかってDialogを呼び出し、その呼び出したDialogから別のDialogを呼び出す方法について書きます。下記のGIFのように1つ目のDialogを呼び出した後、1つ目のDialogの「OK」ボタンを押すと、2つ目のDialogが表示されます。
やり方
ソースコード
上記の動画の動作例は下記のようなコードで実現します。
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setTitle("Dialog Test")
val displayDialog = findViewById<Button>(R.id.button)
displayDialog.setOnClickListener{
val dialog = firstDialog()
val manager: FragmentManager = supportFragmentManager
dialog.show(manager, "simple")
}
}
}
Dialog.kt
// 1つ目のDialog
class firstDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
// Use the Builder class for convenient dialog construction
val builder = AlertDialog.Builder(it)
builder.setTitle("テスト")
.setMessage("1つ目のダイアログ")
.setPositiveButton("OK") { firstDialogInterface, i ->
firstDialogInterface.dismiss()
val nextDialog = secondDialog()
// FragmentManagerの指定
val manager = fragmentManager
if (manager != null) {
nextDialog.show(manager, "simple")
}
}
.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
}
// 2つ目のDialog
class secondDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
// Use the Builder class for convenient dialog construction
val builder = AlertDialog.Builder(it)
builder.setTitle("テスト")
.setMessage("2つ目のダイアログ")
.setPositiveButton("OK") { secondDialogInterface, i ->
secondDialogInterface.dismiss()
}
.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
}
activity_main.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"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dialog"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
失敗するやり方
先程のDialog.ktを下記のようにします。
Dialog.kt
class firstDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
// Use the Builder class for convenient dialog construction
val builder = AlertDialog.Builder(it)
builder.setTitle("テスト")
.setMessage("1つ目のダイアログ")
.setPositiveButton("OK") { secondDialogInterface, i ->
secondDialogInterface.dismiss()
val nextDialog = secondDialog()
//val manager = fragmentManager
// 変更点
val manager: FragmentManager = childFragmentManager
nextDialog.show(manager, "simple")
}
.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
}
class secondDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
// Use the Builder class for convenient dialog construction
val builder = AlertDialog.Builder(it)
builder.setTitle("テスト")
.setMessage("2つ目のダイアログ")
.setPositiveButton("OK") { secondDialogInterface, i ->
secondDialogInterface.dismiss()
}
.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
}
変更点は1つ目のDialogから2つ目のDialogを呼び出す際に、FragmentManagerをchildFragmentManagerを指定しています。
Dialog.kt
val manager: FragmentManager = childFragmentManager
これを動作させると、1つ目のDialog表示後、「OK」ボタンをおすと2つ目のDialogが表示されません。
おわりに
FragmentManagerの仕様を確認すると、childFragmentManagerはFragmentManagerの子要素であることが確認できます。そのため1つ目のDialogの消去にともなって、2つ目のDialogも消去されていると考えられます。そのため、1つ目のDialogと2つ目のDialogの表示では、それぞれのfragmentManagerに分けて指定する必要があります。
これでDialogFragmentで表示したDialogから別のDialogFragmentを呼び出すことができました。
Discussion