Search code examples
androidkotlinfindimageviewfindviewbyid

Get ImageView by ID on different kt file to set image which is in CardView of different kt file


So basically I'm making an activity in which in button click one alert dialog displays on screen and it contain recyclerview with cardview and one close button. now, by clicking on cardview I have successfully toast a message but now there is requirement to get the image of cardview and then set it into imageview of different xml file (that cardview is also in different kt file). In short the main problem is i can not find that imageview into that different kt file.
So, I have tried few approaches mentioned below

  1. First Approach -> view.findViewById (in this case the error is view.findViewById(R.id.custom_image_view) must not be null)
  2. Second Approach -> by using view.find (in this case the error is null cannot be cast to non-null type android.widget.ImageView)
  3. Third Approach -> accessing using className().imageview (in this case the error is lateinit property is not been initialized) method but the problem is still there.

So, below code contains button for displaying alert dialog.
code file named as CreateCustomImageActivity.kt

class CreateCustomImageActivity : AppCompatActivity(), View.OnTouchListener {

    /* some code */

    lateinit var imageView: ImageView
    
    /* some code */
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_create_custom_image)

        /* below is the imageView in which I want to set image */

        imageView = findViewById(R.id.custom_image_view)

        /* below is the imageButton on which by clicking alert dialog with recyclerView
           with cardView is displaying */

        val image = findViewById<ImageButton>(R.id.bg_image)

        image.setOnClickListener {
            val selectImageDialog = LayoutInflater.from(this)
                .inflate(R.layout.activity_choose_background_image_list, null)
            val builder = AlertDialog.Builder(this).setView(selectImageDialog)
            val showDialog = builder.show()
            showDialog.window?.setGravity(Gravity.BOTTOM)

            val close = selectImageDialog.findViewById<Button>(R.id.choose_image)
            val recyclerImageList = selectImageDialog.findViewById<RecyclerView>(R.id.image_list_recycler_view)

            val imageCard = ArrayList<backgroundImageListDatabase>()
            imageCard.add(backgroundImageListDatabase(R.drawable.o))
            imageCard.add(backgroundImageListDatabase(R.drawable.t))
            imageCard.add(backgroundImageListDatabase(R.drawable.th))
            imageCard.add(backgroundImageListDatabase(R.drawable.f))
            imageCard.add(backgroundImageListDatabase(R.drawable.fi))
            imageCard.add(backgroundImageListDatabase(R.drawable.s))
            imageCard.add(backgroundImageListDatabase(R.drawable.se))

            recyclerImageList.setLayoutManager(
                GridLayoutManager(this,2,
                    GridLayoutManager.VERTICAL,false)
            )
            val adapter = BackgroundImageCardAdapter(imageCard)
            recyclerImageList.setAdapter(adapter)

            close.setOnClickListener {
                showDialog.dismiss()
            }
        }
    }
}

And below code contains the Adapter class for binding cardView to recyclerView.
Code file named as ChooseBackgroundImageListActivity.kt

class BackgroundImageCardAdapter(val backgroundImageCardDetails: ArrayList<backgroundImageListDatabase>) :
        RecyclerView.Adapter<BackgroundImageCardAdapter.ViewHolder>() {

            class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {

//                var bgImageView: ImageView = view.find(R.id.custom_image_view)

                fun bindItems(details: backgroundImageListDatabase) {
                    val imageView = itemView.findViewById<ImageView>(R.id.background_image_card_image)

                    imageView.setImageResource(details.image)

                    imageView.setOnClickListener {

//                        bgImageView.setImageResource(details.image)

                        Toast.makeText(imageView.context,details.image.toString(),Toast.LENGTH_SHORT).show()
                        Log.d(" - CARD CLICK EVENT - ","Clicked")
                    }
                }

            }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val cardView: View = LayoutInflater.from(parent.context).inflate(R.layout.choose_background_image_card,parent,false)
        return ViewHolder(cardView)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bindItems(backgroundImageCardDetails[position])

//        holder.itemView.setOnClickListener {
//            Toast.makeText(holder.itemView.context,"CARD CLICKED",Toast.LENGTH_SHORT).show()
//            Log.d(" - CARD CLICK EVENT - ","Clicked")
//        }
    }

    override fun getItemCount(): Int {
        return backgroundImageCardDetails.size
    }
}

Thanks in Advance.


Solution

  • Its not about putting them in the same or different kt file, You cant access any view until you have its reference. I mean you have only access to your imageView when your dialog is on the screen and you can access its value with selectImageDialog.findViewById

    The best option here is using Callbacks(when you click on a image in your adapter the parent of your adapter should get noticed that new image is clicked)

    first create your callback:

    interface CardAdapterCallback {
        fun onImageClicked(resId : Int)
    }
    

    then change your adapter constructor and add your callback:

    class BackgroundImageCardAdapter(
        val backgroundImageCardDetails: ArrayList<backgroundImageListDatabase>,
        val callback : CardAdapterCallback
    ) :RecyclerView.Adapter<BackgroundImageCardAdapter.ViewHolder>() {...}
    

    then when you click on a image in your adapter bindItems function send your callback to your activity:

    fun bindItems(details: backgroundImageListDatabase) {
         val imageView = itemView.findViewById<ImageView>(R.id.background_image_card_image)
    
        imageView.setImageResource(details.image)
        imageView.setOnClickListener {
            callback.onImageClicked(details.image) 
        }
    }
    

    Updated

    change your adapter creating in your activity to this:

    val adapter = BackgroundImageCardAdapter(
        imageCard,
        object : CardAdapterCallback {
             override fun onImageClicked(resId : Int){
                 imageView.setImageResource(resId)
            }
        })
    

    (object:CardAdapterCallback{} is for fixing your parameter error)

    And to fix your callback variable error in bindItems function change this line in your BackgroundImageCardAdapter:

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        fun bindItems(details: backgroundImageListDatabase) {
            val imageView = itemView.findViewById<ImageView>(R.id.background_image_card_image)
    
            imageView.setImageResource(details.image)
            imageView.setOnClickListener {
                callback.onImageClicked(details.image) 
            }
        }
    }
    

    with that inner keyword, you will be able to call callback.onImageClicked(details.image) in your bindItems function