如何使用 StaggeredGridLayoutManager 在 RecyclerView 中确定 viewholder 是左还是右
How to determine viewholder is left or right in RecyclerView with StaggeredGridLayoutManager
我已经阅读了很多类似的文章,但仍然没有找到如何在 RecyclerView
和 StaggeredGridLayoutManager
中知道 view holder 是左还是右的答案。
情况:
我有 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]
所以它不起作用。
我怎么知道是左取景器还是右取景器?
唯一真正有帮助的选项是使用自定义 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));
我已经阅读了很多类似的文章,但仍然没有找到如何在 RecyclerView
和 StaggeredGridLayoutManager
中知道 view holder 是左还是右的答案。
情况:
我有 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]
所以它不起作用。
我怎么知道是左取景器还是右取景器?
唯一真正有帮助的选项是使用自定义 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));