Search code examples
androidkotlinfindviewbyid

How can I pass a variable control name to findViewById in Kotlin?


I am trying to learn Kotlin and I'm building a simple example as I go. I have 3 image buttons that open the camera and take a photo. The thumbnail is then set into an ImageView. I've used the examples from https://developer.android.com/training/camera/photobasics?hl=en to get the basics working (figuring if I can make it work for one, it'll work for all. It does indeed work for one, but I can't figure out how to make it one function that drops the thumbnail into the correct ImageView.

Inside my onCreate I have the listener for each of the buttons that will invoke the camera:

camRead1.setOnClickListener {dispatchTakePictureIntent() }
camRead2.setOnClickListener {dispatchTakePictureIntent() }
camRead3.setOnClickListener {dispatchTakePictureIntent() }

And I took the sample from the url above:

val REQUEST_IMAGE_CAPTURE = 1

private fun dispatchTakePictureIntent() {
    val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
    try {
        startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
    } catch (e: ActivityNotFoundException) {
        // display error state to the user
    }
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)

    val thumb: ImageView = findViewById(R.id.thumbRead1)

    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        val imageBitmap = data.extras.get("data") as Bitmap
        thumb.setImageBitmap(imageBitmap)
    }
}

and pasted it into my class MainActivity, and after I replaced imageView in the override function with a variable (thumb) and added the super, it worked perfectly for the first one.

However, I am trying to get 3 photos, read1, read2, and read3 which each need to display the thumb in thumbRead1, thumbRead2 and thumbRead3. I can't figure out how the onActivityResult is executed since the call inside dispatchTakePictureIntent is calling startActivityForResult (especially as Android Studio says that startActivityForResult is deprecated).

Obviously, once onActivityResult executes, I can see that thumb defines R.id.thumbRead1 and receives imageBitmap but I don't understand how I can make it aware of the button that was clicked.

Without understanding how onActivityResult is called, I'm thinking that if I can do something like:

findViewById(R.id("thumbRead" + imgID))

to define the specific ImageView that I want the photo pasted into. Am I on the right track here? If not, what is the recommended way of doing this?


Solution

  • Note they've recently added what's supposed to be a cleaner way of starting other activities for results and getting the results, explained here. But since you're already doing it the traditional way, I'll explain how to get that working.

    I think the easiest thing to do in this situation is just make more request codes, so you can check which request it was.

    val REQUEST_IMAGE_CAPTURE_SOURCE_1 = 1
    val REQUEST_IMAGE_CAPTURE_SOURCE_2 = 2
    val REQUEST_IMAGE_CAPTURE_SOURCE_3 = 3
    
    //...
    
    camRead1.setOnClickListener { dispatchTakePictureIntent(REQUEST_IMAGE_CAPTURE_SOURCE_1) }
    camRead2.setOnClickListener { dispatchTakePictureIntent(REQUEST_IMAGE_CAPTURE_SOURCE_2) }
    camRead3.setOnClickListener { dispatchTakePictureIntent(REQUEST_IMAGE_CAPTURE_SOURCE_3) }
    
    //...
    
    private fun dispatchTakePictureIntent(requestCode: Int) {
        val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        try {
            startActivityForResult(takePictureIntent, requestCode)
        } catch (e: ActivityNotFoundException) {
            // display error state to the user
        }
    }
    
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (resultCode != RESULT_OK) {
            // possibly show message to user
            return 
        }
        val imageViewId = when (requestCode) {
            REQUEST_IMAGE_CAPTURE_SOURCE_1 -> R.id.thumbRead1
            REQUEST_IMAGE_CAPTURE_SOURCE_2 -> R.id.thumbRead2
            REQUEST_IMAGE_CAPTURE_SOURCE_3 -> R.id.thumbRead3
        }
        val imageView = findViewById<ImageView>(imageViewId)
        imageView.imageBitmap = data.extras.get("data") as Bitmap
    }
    

    By the way, if you want to get an ID for a view using the String like you were showing you were trying, you would do it like this:

    val viewId = resources.getIdentifier("thumbRead$imgId", "id", packageName)
    val imageView = findViewById<ImageView>(viewId)