如何使用 StaggeredGridLayoutManager 在 RecyclerView 中确定 viewholder 是左还是右

Posted

技术标签:

【中文标题】如何使用 StaggeredGridLayoutManager 在 RecyclerView 中确定 viewholder 是左还是右【英文标题】:How to determine viewholder is left or right in RecyclerView with StaggeredGridLayoutManager 【发布时间】:2018-10-15 01:18:07 【问题描述】:

我已经阅读了很多类似的文章,但仍然没有找到答案如何在RecyclerViewStaggeredGridLayoutManager 中知道视图持有者是左还是右。

情况: 我有RecyclerView,StaggeredGrid 并且想要像这样进行填充

8 dp [left view] 8 dp [right view] 8 dp

因此,由于我无法在 XML 中执行此操作,因此我必须添加一些边距 -

对于左视图:左边距 8dp,右边距 4dp

对于右视图:左边距 4dp,右边距 8dp

通常视图是这样放置的:

[0][1]
[2][3]
[4][5]

所以最简单的解决方案是尝试通过位置来确定它:

override fun onBindViewHolder(ViewHolder holder, int position) 
    ...
        val params = holder.cardView.layoutParams as FrameLayout.LayoutParams

        if (position % 2 == 0) 
            params.leftMargin = pxFromDp(context, 8f).toInt()
            params.rightMargin = pxFromDp(context, 4f).toInt()
        
        if (position % 2 == 1) 
            params.rightMargin = pxFromDp(context, 8f).toInt()
            params.leftMargin = pxFromDp(context, 4f).toInt()
        
        params.bottomMargin = pxFromDp(context, 2f).toInt()
        params.topMargin = pxFromDp(context, 6f).toInt()

        holder.cardView.layoutParams = params
    ...

这行得通,但是如果视图 2 的高度小于视图 1,则它们被放置

[0][1]
[3][2]
[5][4]

所以它不起作用。

我怎么知道是左视图还是右视图?

【问题讨论】:

【参考方案1】:

唯一真正有帮助的选项是使用自定义RecyclerView.ItemDecoration()

class StaggeredGridDecoration(val margin: Int) : RecyclerView.ItemDecoration() 
    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) 
        super.getItemOffsets(outRect, view, parent, state)
        val position = parent.getChildAdapterPosition(view)
        val spanIndex = (view.layoutParams as StaggeredGridLayoutManager.LayoutParams).spanIndex
        val type = parent.adapter.getItemViewType(position)
        val halfOfMargin = margin / 2
        when (type) 
            1 -> //use here 0 if you didnt create custom types
                var top = 0
                val bottom = pxFromDp(parent.context, margin.toFloat()).toInt()
                //for first 2 elements I need additional margin top
                if (position < 3) 
                    top = pxFromDp(parent.context, margin.toFloat()).toInt()
                
                if (spanIndex == 0) 
                    //settings for left column
                    val left = pxFromDp(parent.context, margin.toFloat()).toInt()
                    val right = pxFromDp(parent.context, halfOfMargin.toFloat()).toInt()
                    setMargins(view, left, right, top, bottom)
                 else 
                    //settings for right column
                    val left = pxFromDp(parent.context, halfOfMargin.toFloat()).toInt()
                    val right = pxFromDp(parent.context, margin.toFloat()).toInt()
                    setMargins(view, left, right, top, bottom)
                
            
        
    

    private fun setMargins(view: View, left: Int, right: Int, top: Int, bottom: Int) 
        val cardView: CardView = view.findViewById(R.id.cardView)
        val params = cardView.layoutParams as FrameLayout.LayoutParams

        params.rightMargin = right
        params.leftMargin = left
        params.bottomMargin = bottom
        params.topMargin = top

        cardView.layoutParams = params
    


刚刚添加了它

recyclerView.addItemDecoration(new StaggeredGridDecoration(8));

【讨论】:

以上是关于如何使用 StaggeredGridLayoutManager 在 RecyclerView 中确定 viewholder 是左还是右的主要内容,如果未能解决你的问题,请参考以下文章

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等

如何使用 Math.Net 连接矩阵。如何使用 Math.Net 调用特定的行或列?

WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?