如何在选择时将项目设置为 Recycler View 的中心

20

我正在使用 RecyclerView 水平展示项目。我想将所选项目设置为视图的中心,就像这样:

enter image description here

这是我的做法:

LinearLayoutManager layoutManager
                = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        recyclerView.setLayoutManager(layoutManager);

1
请提供您想要实现的内容和迄今为止尝试过的内容的屏幕截图。 - TejjD
尝试使用 ViewPager 替代 RecyclerView。 - Sanif SS
@Ravi,你找到任何解决方案了吗? - Parth Srivastav
1
有类似的问题。这个答案可以帮助你:https://dev59.com/TVsW5IYBdhLWcg3wyJt3#34647005 - TheSecond
5个回答

12

要从RecyclerView中获取屏幕中间的项,您可以将OnScrollListener附加到RecyclerView上,在侦听器内部,您应该获取当前项目的位置,然后检查给定项目的区域是否位于屏幕中间。

Kotlin代码示例:

// Attach OnScrollListener to your RecyclerView
addOnScrollListener(object : RecyclerView.OnScrollListener() {
    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        recyclerView.post {
            selectMiddleItem()
        }
    }
})
// implementation of method that is called from OnScrollListener
private fun selectMiddleItem() {
    val firstVisibleIndex = layoutManager.findFirstVisibleItemPosition()
    val lastVisibleIndex = layoutManager.findLastVisibleItemPosition()
    val visibleIndexes = listOf(firstVisibleIndex..lastVisibleIndex).flatten()

    for (i in visibleIndexes) {
        val vh = findViewHolderForLayoutPosition(i)
        if (vh?.itemView == null) {
            continue
        }
        val location = IntArray(2)
        vh.itemView.getLocationOnScreen(location)
        val x = location[0]
        val halfWidth = vh.itemView.width * .5
        val rightSide = x + halfWidth
        val leftSide = x - halfWidth
        val isInMiddle = screenWidth * .5 in leftSide..rightSide
        if (isInMiddle) {
            // "i" is your middle index and implement selecting it as you want 
            // optionsAdapter.selectItemAtIndex(i)
            return
        }
    }
}

最终结果应该是这样的:

输入图像描述


1
这是什么意思 ->? findViewHolderForLayoutPosition - Prince Dholakiya
@DPrince,那是RecyclerView类中的方法。在这里查看:https://developer.android.com/reference/android/support/v7/widget/RecyclerView#findviewholderforlayoutposition - Paweł Kanarek
在Android Studio中,您可以自动将Kotlin代码转换为Java代码,反之亦然。 - Paweł Kanarek
这是什么 -> selectItemAtIndex @PawełKanarek - Bipin Bharti
1
请问您能否分享整个代码? - Muhammad Farhan Arif
显示剩余2条评论

8

这是为了在滚动或单击项目时将其捕捉到屏幕中心。

您需要为RecyclerView添加SnapHelper。以下是方法:

final RecyclerView recyclerViewObject = view.findViewById(R.id.recyclerViewObjectId);

final LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerViewObject);

recyclerViewObject.setOnFlingListener(snapHelper);

然后您只需调用此代码

recyclerViewObject.addOnItemTouchListener(
            new RecyclerItemClickListener(getContext(), recyclerViewObject ,new RecyclerItemClickListener.OnItemClickListener() {
                @Override public void onItemClick(View view, int position) {
                    recyclerViewObject.smoothScrollToPosition(position);
                }

                @Override public void onLongItemClick(View view, int position) {
                }
            })
    );

5
您可以用更少的代码实现相同的输出。其中,view 是所选适配器项的视图,StaticData.SCREEN_WIDTH 是设备的宽度。
    View view = rvCategory.getChildAt(pos);
    if (view == null)
        return;
    int scrollX = (view.getLeft() - (StaticData.SCREEN_WIDTH / 2)) + (view.getWidth() / 2);
    rvCategory.smoothScrollBy(scrollX, 0);

在获取视图时,请使用布局管理器。否则它会返回null。val view: View? = headerRv.layoutManager?.findViewByPosition(pos) - thebadassdev

3
请尝试这种解决方案排序:
LinearLayoutManager layoutManager = ((LinearLayoutManager)recyclerView.getLayoutManager());
int totalVisibleItems = layoutManager.findLastVisibleItemPosition() - layoutManager.findFirstVisibleItemPosition()    
int centeredItemPosition = totalVisibleItems / 2;
    recyclerView.smoothScrollToPosition(position);
    recyclerView.setScrollY(centeredItemPosition );

希望这能帮到您。

4
RecyclerView没有getLastVisiblePosition、getFirstVisiblePosition方法,也不支持smoothScrollByOffset方法。 - ravi
1
谢谢Saeed,但是getLastVisiblePosition和getFirstVisiblePosition在RecyclerView中不可用。 - ravi
2
@ravi,那些是“LayoutManager”方法。 - Kaloyan Roussev
3
recyclerView.smoothScrollToPosition(position); 这里的 position 是指滑动到哪个位置? - Prince Dholakiya
如果我正确理解这段代码,它将把视图的顶部放置在屏幕中央,而不是视图本身(即其中心)。 - Ivan Ičin
显示剩余2条评论

2
将您的自定义布局管理器定义为:
class CenterLayoutManager : LinearLayoutManager {
    constructor(context: Context) : super(context)
    constructor(context: Context, orientation: Int, reverseLayout: Boolean) : super(context, orientation, reverseLayout)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)

    override fun smoothScrollToPosition(recyclerView: RecyclerView, state: RecyclerView.State, position: Int) {
        val centerSmoothScroller = CenterSmoothScroller(recyclerView.context)
        centerSmoothScroller.targetPosition = position
        startSmoothScroll(centerSmoothScroller)

    }

    private class CenterSmoothScroller(context: Context) : LinearSmoothScroller(context) {
        override fun calculateDtToFit(viewStart: Int, viewEnd: Int, boxStart: Int, boxEnd: Int, snapPreference: Int): Int = (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2)
    }
}

然后将此布局管理器分配给您的 RecyclerView。
myRecyclerview.layoutManager =
        CenterLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)

在RecyclerView的项(item)的onClick方法中使用。
myRecyclerview.smoothScrollToPosition(position)

“position应该从onBindViewHolder中获取”
“同时使用LinearSnapHelper”
 val snapHelper = LinearSnapHelper()
    snapHelper.attachToRecyclerView(myRecyclerview)

它将有效控制滚动。
还要将滚动监听器附加到RecyclerView上,以获取居中位置的项目。
Recyclerview.setOnScrollListener(object:
            RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                var view=recyclerView[0]

            }
        })

请查看这个stackoverflow答案以获取更多细节:check out this stackoverflow answer for more details

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接