如何在 recyclerView 中找到锚点内部项目
How to find anchor inner item in recyclerView
我遇到了一个小问题,我需要从 recyclerView 中心可见项目中找到锚项目
请查看下图以供参考
下面是我用来从 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
}
}
我想在 recyclerView 中找到内部锚项目,但无法在 recyclerView 中找到准确的中心可见内部项目
我能找到 recyclerView 的中心可见项,但找不到锚点内部项
这是相同的参考视频
https://drive.google.com/file/d/1OIPq-YOFhch6xFpSZGEFZTDHhDisicDg/view?usp=sharing
想法是锚视图离中心更近:
首先获取居中item在屏幕上的x位置(即左边缘),加上item宽度得到右边缘;然后将其与屏幕的中心点进行比较,以了解哪个边缘更接近中心。
但首先,我们需要获取与居中项目关联的 ViewHolder
实例,以获取这些位置并访问基础视图。
您已经在 onScrollStateChanged()
回调中获得 RecyclerView
中居中项目 (middleItemIndex
) 的位置。然后获取此位置的关联 ViewHolder
实例:
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 ...)
您可以将居中的项目分成3等份,其中将有两条边与屏幕中心位置进行比较:
// 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
}
}
我遇到了一个小问题,我需要从 recyclerView 中心可见项目中找到锚项目
请查看下图以供参考
下面是我用来从 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
}
}
我想在 recyclerView 中找到内部锚项目,但无法在 recyclerView 中找到准确的中心可见内部项目
我能找到 recyclerView 的中心可见项,但找不到锚点内部项
这是相同的参考视频
https://drive.google.com/file/d/1OIPq-YOFhch6xFpSZGEFZTDHhDisicDg/view?usp=sharing
想法是锚视图离中心更近:
首先获取居中item在屏幕上的x位置(即左边缘),加上item宽度得到右边缘;然后将其与屏幕的中心点进行比较,以了解哪个边缘更接近中心。
但首先,我们需要获取与居中项目关联的 ViewHolder
实例,以获取这些位置并访问基础视图。
您已经在 onScrollStateChanged()
回调中获得 RecyclerView
中居中项目 (middleItemIndex
) 的位置。然后获取此位置的关联 ViewHolder
实例:
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 ...)
您可以将居中的项目分成3等份,其中将有两条边与屏幕中心位置进行比较:
// 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
}
}