I'm stuck in one small issue, where i need to find anchor item from recyclerView center visible item
Please check below image for reference

below code i'm using to find center item from recyclerView
class CenterItemFinder(
private val context: Context,
private val layoutManager: LinearLayoutManager,
private val callback: CenterItemCallback,
private val controlState: Int
) : OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
if (controlState == ALL_STATES || newState == controlState) {
val firstVisible = layoutManager.findFirstVisibleItemPosition()
val lastVisible = layoutManager.findLastVisibleItemPosition()
val itemsCount = lastVisible - firstVisible + 1
val screenCenter = context.resources.displayMetrics.widthPixels / 2
var minCenterOffset = Int.MAX_VALUE
var middleItemIndex = 0
for (index in 0 until itemsCount) {
val listItem = layoutManager.getChildAt(index) ?: return
val leftOffset = listItem.left
val rightOffset = listItem.right
val centerOffset =
Math.abs(leftOffset - screenCenter) + Math.abs(rightOffset - screenCenter)
if (minCenterOffset > centerOffset) {
minCenterOffset = centerOffset
middleItemIndex = index + firstVisible
}
}
callback.scrollFinished(middleItemIndex)
}
}
interface CenterItemCallback {
fun scrollFinished(middleElement: Int)
}
companion object {
const val ALL_STATES = 10
}
}
I want to find inner anchor item in recyclerView but not able to find exact center visible inner item in recyclerView
i'm able to find the center visible item of recyclerView but not able to find anchor inner item
Here is the reference video for the same
https://drive.google.com/file/d/1OIPq-YOFhch6xFpSZGEFZTDHhDisicDg/view?usp=sharing
The idea is that the anchor view is that closer to the center:
First get the x position of the centered item on the screen (i.e. left edge), add the item width to get the right edge; then compare that to center point of the screen to know which edge is closer to the center.
But first, we need to get the ViewHolder instance associated to that centered item to get these positions & access the underlying views.
You already got the position of the centered item (middleItemIndex) in the RecyclerView within the onScrollStateChanged() callback. Then to get the associated ViewHolder instance for this position:
val holder =
recyclerView.findViewHolderForAdapterPosition(middleItemIndex) as MyViewHolder // Cast that to your ViewHolder class
// Get the centered item position on the screen
val point = IntArray(2)
holder.itemView.getLocationOnScreen(point) // or getLocationInWindow(point)
val leftEdge = point[0]
val rightEdge = leftEdge + holder.itemView.width
val screenCenter = resources.displayMetrics.widthPixels / 2
val leftOffset = Math.abs(leftEdge - screenCenter)
val rightOffset = Math.abs(rightEdge - screenCenter)
// And eventually get the anchor view:
val anchorView = if (leftOffset > rightOffset) {
// The right view is the anchor
holder.itemView.findViewById<...>(R.id.rightItemId) // adjust rightItemId to your most right view id in the RV item
} else {
// The left view is the anchor
holder.itemView.findViewById<...>(R.id.leftItemId) // adjust leftItemId to your most left view id in the RV item
}
using this condition if (leftOffset > rightOffset) { i'm able to detect first and last block from recyclerview, the issue is that i'm not able to detect the center block item (the item which have ...)
You can divide the centered item into 3 equal parts, where there will be two edges to compare to the screen center position:
// Get the centered item x,y position on the screen
val point = IntArray(2)
holder.itemView.getLocationOnScreen(point) // or getLocationInWindow(point)
val itemWidth = holder.itemView.width
// Divide the width into 3 equal parts (two margins)
val leftMargin = point[0] + itemWidth / 3
val rightMargin = point[0] + itemWidth * 2 / 3
val anchorView =
when {
screenCenter > rightMargin -> {
// The anchor is the right item
holder.itemView.findViewById<..>(R.id.rightItemId) // adjust rightItemId to the most right view id in the RV item
}
screenCenter > leftMargin -> {
// The anchor is the middle item
holder.itemView.findViewById<..>(R.id.middleItemId) // adjust rightItemId to the middle view id in the RV item
}
else -> {
// The anchor is the left item
holder.itemView.findViewById<..>(R.id.leftItemId) // adjust rightItemId to the most left view id in the RV item
}
}