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
中,我只是更新背景或图像视图,而不是项目(或者,可能是任何可能会影响布局宽度的内容)。
我正在使用 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
中,我只是更新背景或图像视图,而不是项目(或者,可能是任何可能会影响布局宽度的内容)。