How to add onClickListener which opens gallery inside popupWindow

48 Views Asked by At

so i want to add video, and image selection inside a popupWindow and later add all of this inside recyclerView. But when i try to open my popupWindow app crashes, i checked my logcat and i understand why my app don't work (I think) but i don't know how to solve this inside my code.

here is an preview of what it looks like without any functionality

i wanted to do this with 'startActivityForResult' but this method is depreciated and way more complicated for me

MainActivity.kt

class MainActivity : AppCompatActivity() {

private val home = HomeFragment()
private val player = PlayerFragment()
private val profile = ProfileFragment()
private val settings = SettingsFragment()


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

    val popupButton: FloatingActionButton = findViewById(R.id.fab)
    val bottomNav: BottomNavigationView = findViewById(R.id.bottomNavigationView)

    bottomNav.background = null
    bottomNav.menu.findItem(R.id.placeholder).isEnabled = false
    replaceFragment(home)

    bottomNav.setOnItemSelectedListener {
        when (it.itemId) {
            R.id.home -> replaceFragment(home)
            R.id.player -> replaceFragment(player)
            R.id.profile -> replaceFragment(profile)
            R.id.settings -> replaceFragment(settings)
        }
        true
    }
    popupButton.setOnClickListener {
        showDialog()
    }

}
private fun replaceFragment(fragment: Fragment) {
    val transaction = supportFragmentManager.beginTransaction()
    transaction.replace(R.id.fragment_container, fragment)
    transaction.commit()
}

private fun showDialog() {

    val title = RecyclerAdapter().titles
    val description = RecyclerAdapter().details
    val video = RecyclerAdapter().videos

    val dialog = Dialog(this)
    val dialogView: View = layoutInflater.inflate(R.layout.popup, null)

    val imageView = dialogView.findViewById<ImageView>(R.id.imageChange)
    val videoView = dialogView.findViewById<ImageView>(R.id.VideoSelect)

    val titleEditText = dialogView.findViewById<EditText>(R.id.titleEdit) //popUp edit field title
    val descEditText = dialogView.findViewById<EditText>(R.id.description) //popUp pole edit field description

    val getPreviewImage = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
        imageView.setImageURI(it)
    })
    val getPreviewVideo = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
        videoView.setImageURI(it)
    })


    dialogView.addImage?.setOnClickListener {
        getPreviewImage.launch("image/*")
    }

    dialogView.addVideo?.setOnClickListener {
        getPreviewVideo.launch("video/*")
    }

    dialogView.addButton?.setOnClickListener {
        if (titleEditText.text.isEmpty()){
            Toast.makeText(applicationContext, "add required data", Toast.LENGTH_SHORT).show()
        }else{
            Toast.makeText(applicationContext, "Added", Toast.LENGTH_SHORT).show()
        }
    }
    dialog.setContentView(dialogView)
    dialog.show()
 }
}

debug console

E/AndroidRuntime: FATAL EXCEPTION: main
Process: eu.tuto.youtubeproject, PID: 15323
java.lang.IllegalStateException: LifecycleOwner eu.tuto.youtubeproject.MainActivity@4f4d646 is attempting to register while current state is RESUMED. LifecycleOwners must call register before they are STARTED.
    at androidx.activity.result.ActivityResultRegistry.register(ActivityResultRegistry.java:123)
    at androidx.activity.ComponentActivity.registerForActivityResult(ComponentActivity.java:682)
    at androidx.activity.ComponentActivity.registerForActivityResult(ComponentActivity.java:691)
    at eu.tuto.youtubeproject.MainActivity.showDialog(MainActivity.kt:85)
    at eu.tuto.youtubeproject.MainActivity.onCreate$lambda-1(MainActivity.kt:60)
    at eu.tuto.youtubeproject.MainActivity.$r8$lambda$pybEQF7uXWpGKgIZJas8o7AXY1Q(Unknown Source:0)
    at eu.tuto.youtubeproject.MainActivity$$ExternalSyntheticLambda3.onClick(Unknown Source:2)
    at android.view.View.performClick(View.java:7191)
    at android.view.View.performClickInternal(View.java:7164)
    at android.view.View.access$3500(View.java:821)
    at android.view.View$PerformClick.run(View.java:27856)
    at android.os.Handler.handleCallback(Handler.java:914)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:224)
    at android.app.ActivityThread.main(ActivityThread.java:7551)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:995)
2

There are 2 best solutions below

0
Gregory On BEST ANSWER

Look into docs. You should call for registerForActivityResult before your lifecycle is in START state. It's absolutely legit to call registerForActivityResult initializing member variables.

private val home = HomeFragment()
private val player = PlayerFragment()
private val profile = ProfileFragment()
private val settings = SettingsFragment()
val getPreviewImage = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
        // your logic 
    })
val getPreviewVideo = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
       // your logic 
    })

override fun onCreate(savedInstanceState: Bundle?)
...
0
Dominik On

Okey, now with help of @Janush FM i figured it out. i moved variables with registerForActivityResult up

class MainActivity : AppCompatActivity() {

private val home = HomeFragment()
private val player = PlayerFragment()
private val profile = ProfileFragment()
private val settings = SettingsFragment()

private val getPreviewImage = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
    imageChange.setImageURI(it)
})
val getPreviewVideo = registerForActivityResult(ActivityResultContracts.GetContent(), ActivityResultCallback {
    VideoSelect.setImageURI(it)
})

where imageChange and VideoSelect are Id's of my ImageView inside PopupWindow, and setonClickListener is inside ShowDialog() function

private fun showDialog() {

    val title = RecyclerAdapter().titles
    val description = RecyclerAdapter().details
    val video = RecyclerAdapter().videos

    val dialog = Dialog(this)
    val dialogView: View = layoutInflater.inflate(R.layout.popup, null)

    val imageView = dialogView.findViewById<ImageView>(R.id.imageChange)
    val videoView = dialogView.findViewById<ImageView>(R.id.VideoSelect)

    val titleEditText = dialogView.findViewById<EditText>(R.id.titleEdit) //popUp edit field title
    val descEditText = dialogView.findViewById<EditText>(R.id.description) //popUp pole edit field description


    dialogView.addImage?.setOnClickListener {
        getPreviewImage.launch("image/*")
    }

    //dialogView.addVideo?.setOnClickListener {
        //getPreviewVideo.launch("video/*")
    //}

    dialogView.addButton?.setOnClickListener {
        if (titleEditText.text.isEmpty()){
            Toast.makeText(applicationContext, "add required data", Toast.LENGTH_SHORT).show()
        }else{
            Toast.makeText(applicationContext, "Added", Toast.LENGTH_SHORT).show()
        }
    }
    dialog.setContentView(dialogView)
    dialog.show()
}