I cannot figure this strange behaviour out.
This randomly happens on some device and always on a Honor 9 STF-L9 (the one on the gif animation).
If you look at this gif, you can see that coming back from the pick chooser, the dialog is visible again, even if no one is showing it (see the full image gif by clicking on it to see the video).
I've a single Activity
application (I use the new Navigation jetpack component) and I have a custom AlertDialog
in my MainActivity
:
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding
private lateinit var inflater: LayoutInflater
private lateinit var dialogView: View
private lateinit var messageTextView: TextView
private val progressHud: AlertDialog by lazy {
val dialogBuilder =
AlertDialog.Builder(this, R.style.ProgressHudTheme)
messageTextView.visibility = View.GONE
dialogBuilder.setView(dialogView)
dialogBuilder.setCancelable(false)
dialogBuilder.create()
}
fun showProgressHud(message: String?) {
messageTextView.visibility = View.GONE
message?.let {
messageTextView.text = it
messageTextView.visibility = View.VISIBLE
}
progressHud.show()
}
fun hideProgressHud() {
progressHud.hide()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
setSupportActionBar(binding.toolbar)
val navController = findNavController(R.id.nav_host_fragment_content_main)
appBarConfiguration = AppBarConfiguration(navController.graph)
setupActionBarWithNavController(navController, appBarConfiguration)
binding.fab.setOnClickListener { view ->
dispatchChoosePictureFromGalleryAppIntentIntent()
}
setupProgressHud()
}
private fun dispatchChoosePictureFromGalleryAppIntentIntent() {
Intent(
Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
).apply {
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
resolveActivity(packageManager)?.also {
requestImageChooserLauncher.launch(this)
}
}
}
private var requestImageChooserLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
val resultCode = result.resultCode
val data = result.data
// TODO ...
}
private fun setupProgressHud() {
inflater = getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
dialogView = inflater.inflate(R.layout.progress_hud, null)
messageTextView = dialogView.findViewById(R.id.progressHudTextView)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
return when (item.itemId) {
R.id.action_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
override fun onSupportNavigateUp(): Boolean {
val navController = findNavController(R.id.nav_host_fragment_content_main)
return navController.navigateUp(appBarConfiguration)
|| super.onSupportNavigateUp()
}
}
The Dialog is shown and hidden this way in the FirstFragment
:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.buttonFirst.setOnClickListener {
(activity as? MainActivity)?.showProgressHud("Loading...")
Handler().postDelayed({
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
(activity as? MainActivity)?.hideProgressHud()
}, 5000)
}
}
And you can find a complete working example here: https://github.com/shadowsheep1/android-alert-dialog-glitch
I still haven't figure why this happens out.
If someone had encountered this before or have any clues would be appreciated.
Try replacing
progressHud.hide()
by
progressHud.dismiss().
That should work fine.
There's a more important reason behind using dismiss()
over hide()
: using hide()
could cause a Leaked Window Error, as it does not really remove the view, just hides it, and then if you finish the activity that might cause leakage.