android - 如何在 Kotlin 的 RecyclerView 中返回位置?
问题描述
我正在使用水平 RecyclerView 和 SnapHelper(以便在移动结束时图像最终位于相同的位置)。
因此,当图像停止移动时,我希望能够在 MainActivity.kt 中显示结果(RecyclerView 位置)?
我不确定这是否需要在适配器或 SnapHelder 中完成?任何帮助都非常感谢 - 我正在努力解决这个问题!
谢谢
用户适配器.kt
class UsersAdapter(
private val users: ArrayList<User>
) : RecyclerView.Adapter<UsersAdapter.DataViewHolder>() {
class DataViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(user: User) {
itemView.textViewUserName.text = user.name
Glide.with(itemView.imageViewAvatar.context)
.load(user.avatar)
.into(itemView.imageViewAvatar)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
DataViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.item_layout, parent,
false
)
)
override fun getItemCount(): Int = Int.MAX_VALUE
// Lets say your list had 100 items
override fun onBindViewHolder(holder: DataViewHolder, position: Int) {
// position can be larger than 100 (ex 101), because our getItemCount doesn't return actual list size
// so if we receive position as 101, which item should we display?
// that should be item 1. (for 102 -> 2, 201 -> 1) and so on
// this suggests use of modules
val pos = position % users.size
holder.bind(users[pos]) // bind the actual item
// Show the number that is being shown
Log.d(Constraints.TAG, "JH onBindViewHolder:" + pos)
}
}
SnapHelper.kt
class ItemSnapHelper : LinearSnapHelper() {
companion object {
private const val MILLISECONDS_PER_INCH = 100f
private const val MAX_SCROLL_ON_FLING_DURATION_MS = 1000
}
private var context: Context? = null
private var helper: OrientationHelper? = null
private var scroller: Scroller? = null
private var maxScrollDistance: Int = 0
override fun attachToRecyclerView(recyclerView: RecyclerView?) {
if (recyclerView != null) {
context = recyclerView.context
scroller = Scroller(context, DecelerateInterpolator())
} else {
scroller = null
context = null
}
super.attachToRecyclerView(recyclerView)
}
override fun findSnapView(layoutManager: RecyclerView.LayoutManager?): View? =
findFirstView(layoutManager, helper(layoutManager))
override fun calculateDistanceToFinalSnap(layoutManager: RecyclerView.LayoutManager, targetView: View): IntArray {
val out = IntArray(2)
out[0] = distanceToStart(targetView, helper(layoutManager))
return out
}
override fun calculateScrollDistance(velocityX: Int, velocityY: Int): IntArray {
val out = IntArray(2)
val helper = helper ?: return out
if (maxScrollDistance == 0) {
maxScrollDistance = (helper.endAfterPadding - helper.startAfterPadding) / 2
}
scroller?.fling(0, 0, velocityX, velocityY, -maxScrollDistance, maxScrollDistance, 0, 0)
out[0] = scroller?.finalX ?: 0
out[1] = scroller?.finalY ?: 0
return out
}
override fun createScroller(layoutManager: RecyclerView.LayoutManager): RecyclerView.SmoothScroller? {
if (layoutManager !is RecyclerView.SmoothScroller.ScrollVectorProvider)
return super.createScroller(layoutManager)
val context = context ?: return null
return object : LinearSmoothScroller(context) {
override fun onTargetFound(targetView: View, state: RecyclerView.State, action: Action) {
val snapDistance = calculateDistanceToFinalSnap(layoutManager, targetView)
val dx = snapDistance[0]
val dy = snapDistance[1]
val dt = calculateTimeForDeceleration(Math.abs(dx))
val time = Math.max(1, Math.min(MAX_SCROLL_ON_FLING_DURATION_MS, dt))
action.update(dx, dy, time, mDecelerateInterpolator)
}
override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float =
MILLISECONDS_PER_INCH / displayMetrics.densityDpi
}
}
private fun distanceToStart(targetView: View, helper: OrientationHelper): Int {
val childStart = helper.getDecoratedStart(targetView)
val containerStart = helper.startAfterPadding
return childStart - containerStart
}
private fun findFirstView(layoutManager: RecyclerView.LayoutManager?, helper: OrientationHelper): View? {
if (layoutManager == null) return null
val childCount = layoutManager.childCount
if (childCount == 0) return null
var absClosest = Integer.MAX_VALUE
var closestView: View? = null
val start = helper.startAfterPadding
for (i in 0 until childCount) {
val child = layoutManager.getChildAt(i)
val childStart = helper.getDecoratedStart(child)
val absDistanceToStart = Math.abs(childStart - start)
if (absDistanceToStart < absClosest) {
absClosest = absDistanceToStart
closestView = child
}
}
return closestView
}
private fun helper(layoutManager: RecyclerView.LayoutManager?): OrientationHelper {
if (helper == null) {
helper = OrientationHelper.createHorizontalHelper(layoutManager)
}
return helper!!
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
lateinit var adapter: ConcatAdapter
lateinit var userVerticalAdapter: UsersAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupDataInRecyclerView()
}
private fun setupDataInRecyclerView() {
recyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
userVerticalAdapter = UsersAdapter(DataSource.getUser())
val listOfAdapters = listOf(userVerticalAdapter)
adapter = ConcatAdapter(listOfAdapters)
recyclerView.adapter = adapter
// When RV is loaded scroll it to middle, so that user doesn't hit limit on both ends(easily)
recyclerView.scrollToPosition(Int.MAX_VALUE/2)
//addItemDecoration(SpaceItemDecoration(this, R.dimen.divider_space))
ItemSnapHelper().attachToRecyclerView(recyclerView)
}
public fun ShowWhatRecieved(isitthere: Int){
ShowMeIt.text = isitthere.toString()
}
}
解决方案
推荐阅读
- python - 如何在不使用两个 % 的情况下在 python 语句中使用 %
- r - 如何计算一组中的最大值并最小化另一组并取平均时间
- fluent-ui - Fluent UI React 将焦点轮廓颜色更改为主要反转颜色
- error-handling - 密钥派生上的 OpenSSL AES 对称错误
- python - 如何修复模板渲染期间的错误
- express - 如何正确地将快递路线拆分为单独的文件?
- css - 下拉列表左侧的 Bootstrap NAVBAR 项 t
- amazon-web-services - 监控账户中 S3 存储桶的数量
- c - 在结构中查找偏移量
- prometheus - 入口控制器中 request_duration 和 response_duration prometheus 指标之间的区别