Android FlexboxLayoutManager 正在重新创建项目

Android FlexboxLayoutManager recreating items

我正在使用 FlexboxLayoutManager 来显示具有动态宽度的 Recycler View 项目。我面临的问题是,当项目的背景发生变化时,它 reanimates/redraw 所有下一个项目都不是很 attractive/required。

以下屏幕截图显示了用例。每当单行中有 two/more 个宽度不同的项目时,selecting/unselecting 视图将重新创建下一个邻居。

我的代码:

 val managerVal = FlexboxLayoutManager(context, FlexDirection.ROW)
// I have used these properties as well with other combinations showing here for reference
//            managerVal.alignItems = AlignItems.FLEX_START
//            managerVal.justifyContent = JustifyContent.CENTER
            itemView.rvFilterOptions.layoutManager = managerVal
val filterOptionAdapter = FilterOptionAdapter(
                context,
                record.values
            )
itemView.rvFilterOptions.adapter = filterOptionAdapter

我也尝试过更改 Adapter 中的值

val lp = itemView.llFilterValue.getLayoutParams()
            if (lp is FlexboxLayoutManager.LayoutParams) {
               lp.flexGrow = 1.0f
               flexboxLp.flexShrink = 1f
               lp.alignSelf = AlignItems.FLEX_START

            }

更改适配器中项目背景的代码。

if (record.isSelected) {
                itemView.tvFilterValue.setTextColor(
                    AppCompatResources.getColorStateList(
                        context,
                        R.color.textWhite
                    )
                )
                itemView.ivFilterCheck.show()
                itemView.llFilterValue.background =
                    AppCompatResources.getDrawable(
                        context,
                        R.drawable.bg_dark_rectangle_circle_edge
                    )
            } else {
                itemView.tvFilterValue.setTextColor(
                    AppCompatResources.getColorStateList(
                        context,
                        R.color.textNormal
                    )
                )
                itemView.ivFilterCheck.invisible()
                itemView.llFilterValue.background =
                    AppCompatResources.getDrawable(
                        context,
                        R.drawable.bg_gray_rectangle_circle_edge
                    )
            }

显示行为的 gif:

感谢您的宝贵时间。

所以修复最终出现在我的 XML 文件中。

Resoning: 当你使用 flexbox 的 flex-direction wrap 你'允许 flexbox 库处理视图大小。由于我的用例位于嵌套的回收器视图中,我的回收器视图项目之一正在使用 match_parent 属性,这导致在运行时调整视图时发生冲突(这在库级别引起了混乱)。

解决方案是简单地使用 wrap_content 和 flexbox 让库决定视图测量。

我遇到了同样的问题,我认为这是因为我在 onBindViewHolder 函数中通过 DataBinding 在 xml 布局文件中设置了一个变量,导致 TextView我的布局文件要重新创建。这似乎会导致布局管理器重新计算视图是否应该换行,即使文本没有更改。

所以我想在不调用正常绑定函数的情况下更新视图。每当我想将一个项目标记为选中时,我通过使用 notifyItemChanged 和有效负载来解决它,例如:

notifyItemChanged(position: Int, payload: Any?)

由于您要发送负载,因此需要覆盖

onBindViewHolder(holder: MyViewHolder, position: Int, payloads: MutableList<Any>)

需要注意的是这个函数是RecyclerView一直调用的,所以如果你没有payload,你需要调用super函数,或者常规的onBindViewHolder,例如:

override fun onBindViewHolder(holder: MyViewHolder, position: Int, payloads: MutableList<Any>) {
    if (payloads.isEmpty()) return super.onBindViewHolder(holder, position, payloads)
    // I know that I called notifyItemChanged with a Boolean as payload to set the selected state.
    holder.updateSelectedState(payloads.firstOrNull() as? Boolean ?: false)
}

然后在 updateSelectedState 中,我只是更新背景或图像视图,而不是项目(或者,可能是任何可能会影响布局宽度的内容)。