Home > database >  How to access an ImageButton inside a ViewPager
How to access an ImageButton inside a ViewPager

Time:03-31

This is my first question, so hopefully I don't get something wrong or write the wrong details. I have recently gotten into using Android Studio, and currently I am working on making a simple quiz. I used a view pager by following a tutorial and created a ViewPagerAdapter Kotlin file. The view pager has a single ImageButton of id "R.id.currentLvl". Now, whenever I try to access this id in MainActivity by findviewbyid, the app crashes on startup and gives the a null pointer error. Here is the code for MainActivity:

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

    val images = listOf(
        R.drawable.coffee_placeholder,
        R.drawable.coffee_placeholder,
        R.drawable.coffee_placeholder
    )
    val adapter = ViewPagerAdapter(images)
    findViewById<ViewPager2>(R.id.viewPager).adapter = adapter
    findViewById<ImageButton>(R.id.currentLvl).setOnClickListener{
        Toast.makeText(applicationContext, "hi", Toast.LENGTH_SHORT).show()
    }
}

}

And here is the Adapter:

class ViewPagerAdapter(
val images: List<Int>

) : RecyclerView.Adapter<ViewPagerAdapter.ViewPagerViewHolder>() { inner class ViewPagerViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView)

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewPagerViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(R.layout.viewpager_quizlvls, parent, false)
    return ViewPagerViewHolder(view)
}

override fun onBindViewHolder(holder: ViewPagerViewHolder, position: Int) {
    val currentImage = images[position]
    holder.itemView.findViewById<ImageButton>(R.id.currentLvl).setImageResource(currentImage)
}

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

}

If I worded my question wrong, the short version is how do listen to this ImageButton? Do I have its listener in the adapter or the main activity?

CodePudding user response:

You should handle this inside your ViewHolder class. For example, let's say your ViewHolder is ViewPagerViewHolder.Important thing to do it in init so you don't setOnClickListener in each bind.

It should be defined in this way :


class ViewPagerViewHolder(
    private val itemView: View,
    private val onImageButtonClicked: () -> Unit
) : RecyclerView.ViewHolder(itemView) {

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


    init {
        // Depending on what you want click on (can be itemView or image, choose regarding our needs)
        image.setOnClickListener { onImageButtonClicked.invoke() }
    }

    fun bind(resource: Int) {
        image.setImageResource(resource)
    }
}

Now you have to update your Adapter to pass the click event :


class ViewPagerAdapter(
    val images: List<Int>,
    val onImageButtonClicked: () -> Unit 
) : RecyclerView.Adapter<ViewPagerAdapter.ViewPagerViewHolder>() {

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewPagerViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(R.layout.viewpager_quizlvls, parent, false)
    return ViewPagerViewHolder(view) {
         onImageButtonClicked.invoke()
    }
  }

  override fun onBindViewHolder(holder: ViewPagerViewHolder, position: Int) {
    val currentImage = images[position]
    holder.itemView.findViewById<ImageButton>(R.id.currentLvl).setImageResource(currentImage)
  }

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

And finally in your MainActivity, you should do something like :


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

    val images = listOf(
        R.drawable.coffee_placeholder,
        R.drawable.coffee_placeholder,
        R.drawable.coffee_placeholder
    )
    val adapter = ViewPagerAdapter(images, ::onImageButtonClicked)
    findViewById<ViewPager2>(R.id.viewPager).adapter = adapter
  }

  private fun onImageButtonClicked() {
    Toast.makeText(applicationContext, "hi", Toast.LENGTH_SHORT).show()
  }

}
  • Related