I faced an error that actually mustn't occur, because I do exactly the same thing in my project in another screen, and it works there, but doesn't want to work in another screen.
The problem is the following: from an Activity in a result of some action I open up a DialogFragment which contains an image and other views in its layout file. Now I can't understand why, but it works in the first case (you'll see below) but doesn't work in the second...
First case:
Layout XML file (dialog_character_selector.xml):
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="dialogViewModel"
type="neptun.jxy1vz.cluedo.ui.menu.character_selector.CharacterSelectorViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Spinner
android:id="@+id/spinnerCharacter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/ivCharacterCard"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="20dp"
android:src="@drawable/szereplo_hatlap"
app:layout_constraintBottom_toTopOf="@+id/btnStart"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_percent="0.7"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/spinnerCharacter" />
<Button
android:id="@+id/btnStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/start"
android:layout_marginBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:onClick="@{()->dialogViewModel.startGame()}"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
The DialogFragment's Kotlin source code (CharacterSelectorDialog.kt):
package neptun.jxy1vz.cluedo.ui.menu.character_selector
import android.animation.AnimatorInflater
import android.animation.AnimatorSet
import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.appcompat.app.AlertDialog
import androidx.core.animation.doOnEnd
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.DialogFragment
import neptun.jxy1vz.cluedo.R
import neptun.jxy1vz.cluedo.databinding.DialogCharacterSelectorBinding
class CharacterSelectorDialog : DialogFragment(), AdapterView.OnItemSelectedListener {
private lateinit var dialogCharacterSelectorBinding: DialogCharacterSelectorBinding
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
dialogCharacterSelectorBinding = DataBindingUtil.inflate(
LayoutInflater.from(context),
R.layout.dialog_character_selector,
null,
false
)
dialogCharacterSelectorBinding.spinnerCharacter.adapter = ArrayAdapter<String>(
context!!,
android.R.layout.simple_spinner_dropdown_item,
resources.getStringArray(R.array.characters)
)
dialogCharacterSelectorBinding.spinnerCharacter.onItemSelectedListener = this
//I do this due to a card flipping animation, it's not important, not part of my problem
val scale = resources.displayMetrics.density
dialogCharacterSelectorBinding.ivCharacterCard.cameraDistance = 8000 * scale
dialogCharacterSelectorBinding.dialogViewModel = CharacterSelectorViewModel(context!!)
return AlertDialog.Builder(context!!, R.style.Theme_AppCompat_Light_Dialog).setView(dialogCharacterSelectorBinding.root).setTitle(resources.getString(R.string.dialog_character_title)).create()
}
override fun onNothingSelected(parent: AdapterView<*>?) {
dialogCharacterSelectorBinding.ivCharacterCard.setImageResource(R.drawable.szereplo_hatlap)
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
dialogCharacterSelectorBinding.ivCharacterCard.setImageResource(R.drawable.szereplo_hatlap)
(AnimatorInflater.loadAnimator(context, R.animator.card_flip) as AnimatorSet).apply {
setTarget(dialogCharacterSelectorBinding.ivCharacterCard)
start()
doOnEnd {
dialogCharacterSelectorBinding.dialogViewModel!!.setPlayer(position)
val img = when (position) {
0 -> R.drawable.szereplo_ginny
1 -> R.drawable.szereplo_harry
2 -> R.drawable.szereplo_hermione
3 -> R.drawable.szereplo_ron
4 -> R.drawable.szereplo_luna
else -> R.drawable.szereplo_neville
}
dialogCharacterSelectorBinding.ivCharacterCard.setImageResource(img)
}
}
}
}
Second case:
Layout XML file (dialog_helper_card.xml):
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="helperCardDialogViewModel"
type="neptun.jxy1vz.cluedo.ui.dice.card_dialog.helper.HelperCardViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/ivHelperCard"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="20dp"
android:src="@drawable/mento_hatlap"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
I think in the main parts it's just the same as the previous one.
Kotlin source file (HelperCardDialog.kt):
package neptun.jxy1vz.cluedo.ui.dice.card_dialog.helper
import android.animation.AnimatorInflater
import android.animation.AnimatorSet
import android.os.Bundle
import android.view.LayoutInflater
import androidx.appcompat.app.AlertDialog
import androidx.core.animation.doOnEnd
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.DialogFragment
import neptun.jxy1vz.cluedo.R
import neptun.jxy1vz.cluedo.databinding.DialogHelperCardBinding
class HelperCardDialog(private val cardResource: Int) : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): AlertDialog {
val dialogHelperCardBinding = DataBindingUtil.inflate<DialogHelperCardBinding>(LayoutInflater.from(context), R.layout.dialog_helper_card, null, false)
dialogHelperCardBinding.helperCardDialogViewModel = HelperCardViewModel()
(AnimatorInflater.loadAnimator(context, R.animator.card_flip) as AnimatorSet).apply {
setTarget(dialogHelperCardBinding.ivHelperCard)
start()
doOnEnd {
dialogHelperCardBinding.ivHelperCard.setImageResource(cardResource)
}
}
return AlertDialog.Builder(context!!, R.style.Theme_AppCompat_Dialog).setTitle(resources.getString(R.string.got_helper_card)).setNeutralButton(resources.getString(R.string.ok)
) { dialog, _ ->
dialog.dismiss()
}.create()
}
}
That's it. These are my most important files in my problem. Sorry for the lot of code...
I hope you will see where the problem is and tell me what's the solution for it.
Finally I found the error in my code. I left the setView() function call from the second AlertDialog.Builder().
The correct code snippet is:
return AlertDialog.Builder(context!!, R.style.Theme_AppCompat_Dialog)
.setView(dialogHelperCardBinding.root)
.setTitle(resources.getString(R.string.got_helper_card)).setNeutralButton(
resources.getString(R.string.ok)
) { dialog, _ ->
dialog.dismiss()
}.create()