我正在寻找一种使用RecyclerView
和PagerSnapHelper
在项目之间添加空格的方法。
如您在上面的两个图像之间所看到的,有一个黑色的空白。但是这些空间仅在滚动显示中可用。如果scrollState在SCROLL_STATE_IDLE
中,则图像将居中对齐并变为“全宽”。
那是我想要实现的。
我的想法是向我的viewType
添加一个新的“占位符” RecyclerView.Adapter
,并自定义PagerSnapHelper
以“跳过” 占位符viewType
(也可以跳过每秒View
)。
但是,这不起作用。我无法将PagerSnaperHelper
(或SnapHelper
中的PagerSnapHelper
中包含很多重复的代码)更改为我想要的样子。在实施过程中,甚至更进一步,感觉还是有些错误。感觉就像“这不是应该的样子”。
那么-有什么建议或想法可以解决这个问题? 我完全愿意接受所有建议。
免责声明:
我知道我可以为此使用旧的ViewPager
。但是出于特殊原因,我要求实现RecyclerView
。因此,请不要在这里建议使用ViewPager
,谢谢。
答案 0 :(得分:2)
您可以尝试以下操作:
创建两个viewType
,第一个是您的图像,第二个是黑色凹痕。然后在SCROLL_STATE_IDLE
和SCROLL_STATE_SETTLING
处调用smoothScrollToPosition(position)
到所需位置。
val pagerSnapHelper = PagerSnapHelper()
val spacePagerSnapHelper = SpacePagerSnapHelper(pagerSnapHelper)
pagerSnapHelper.attachToRecyclerView(recyclerView)
spacePagerSnapHelper.attachToRecyclerView(recyclerView)
这是SpacePagerSnapHelper
:
/**
* This is an [RecyclerView.OnScrollListener] which will scrolls
* the [RecyclerView] to the next closes position if the
* position of the snapped View (calculated by the given [snapHelper] in [SnapHelper.findSnapView])
* is odd. Because each odd position is a space/placeholder where we want to jump over.
*
* See also [this SO question](https://stackoverflow.com/q/51747104).
*/
class SpacePagerSnapHelper(
private val snapHelper: SnapHelper
) : RecyclerView.OnScrollListener() {
private enum class ScrollDirection {
UNKNOWN, LEFT, RIGHT
}
private var scrollDirection: ScrollDirection = UNKNOWN
fun attachToRecyclerView(recyclerView: RecyclerView) {
recyclerView.addOnScrollListener(this)
}
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
scrollDirection = if (dx > 0) RIGHT else LEFT
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
when (newState) {
RecyclerView.SCROLL_STATE_IDLE -> onPageChanged(recyclerView)
RecyclerView.SCROLL_STATE_SETTLING -> onPageChanged(recyclerView)
}
}
private fun onPageChanged(recyclerView: RecyclerView) {
val layoutManager = recyclerView.layoutManager
val viewToSnap = snapHelper.findSnapView(layoutManager)
viewToSnap?.let {
val position = layoutManager.getPosition(it)
// Only "jump over" each second item because it is a space/placeholder
// see also MediaContentAdapter.
if (position % 2 != 0) {
when (scrollDirection) {
LEFT -> {
recyclerView.smoothScrollToPosition(position - 1)
}
RIGHT -> {
recyclerView.smoothScrollToPosition(position + 1)
}
UNKNOWN -> {
Timber.i("Unknown scrollDirection... Don't know where to go")
}
}
}
}
}
}
答案 1 :(得分:0)
UgAr0FF的解决方案通常可以使用,但是也会导致不必要的滚动行为:
如您所见,PagerSnapHelper首先尝试着重于分隔线,然后决定移至下一项。我修复了滚动行为,使其看起来像这样:
这是代码:
import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE
import androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_SETTLING
class PagerSnapAndSkipDividerHelper : PagerSnapHelper() {
private var dx = 0
override fun attachToRecyclerView(recyclerView: RecyclerView?) {
super.attachToRecyclerView(recyclerView)
recyclerView?.addOnScrollListener(onScrollListener)
}
override fun findTargetSnapPosition(
layoutManager: RecyclerView.LayoutManager?,
velocityX: Int,
velocityY: Int
): Int = getNextNonDividerPosition(
super.findTargetSnapPosition(layoutManager, velocityX, velocityY)
)
private fun getNextNonDividerPosition(position: Int) =
if (position % 2 == 0) position else if (dx > 0) position + 1 else position - 1
private val onScrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
this@PagerSnapAndSkipDividerHelper.dx = dx
}
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
if (listOf(SCROLL_STATE_IDLE, SCROLL_STATE_SETTLING).contains(newState)) {
val viewToSnapTo = findSnapView(recyclerView.layoutManager) ?: return
val position = recyclerView.layoutManager?.getPosition(viewToSnapTo) ?: return
val nonDividerPosition = getNextNonDividerPosition(position)
if (position != nonDividerPosition) {
recyclerView.smoothScrollToPosition(nonDividerPosition)
}
}
}
}
}
像这样设置:
PagerSnapAndSkipDividerHelper().attachToRecyclerView(recyclerView)