ViewPager
snaps to a view after you perform some scrolling, and so can RecyclerView
, if you use something like this:
Seems that for ViewPager, I could use the onPageSelected callback to get which item it's about to settle on.
So here's the solution for ViewPager (using the library I used) :
val inflater = LayoutInflater.from(this)
val viewPagerHolders = HashMap()
viewPager.adapter = object : RecyclerPagerAdapter() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewPagerViewHolder {
return ViewPagerViewHolder(inflater.inflate(R.layout.cell, parent, false))
}
override fun getItemCount(): Int = 100
override fun onBindViewHolder(holder: ViewPagerViewHolder, position: Int) {
holder.textView.text = position.toString()
viewPagerHolders.remove(holder.adapterPosition)
holder.adapterPosition = position
viewPagerHolders[position] = holder
}
}
viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
var selectedHolder: ViewPagerViewHolder? = null
override fun onPageScrollStateChanged(state: Int) {}
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
override fun onPageSelected(position: Int) {
val holder = viewPagerHolders[position]
if (holder != null) {
if (selectedHolder != null && selectedHolder != holder)
selectedHolder!!.textView.text = selectedHolder!!.adapterPosition.toString()
holder.textView.text = "selected:${position.toString()}"
selectedHolder = holder
}
}
})
And a ViewHolder class that just remembers which adapter position is associated with it (because this is missing for some reason) :
class ViewPagerViewHolder(itemView: View) : RecyclerPagerAdapter.ViewHolder(itemView) {
val textView: TextView = itemView.findViewById(android.R.id.text1)
var adapterPosition: Int = Int.MIN_VALUE
}
Since it works so well, I decided I will use it, even without blocking touch events functionality.
Still could be nice to know how to do it for RecyclerView.
EDIT: for RecyclerView, this can be done: https://stackoverflow.com/a/47580753/878126