目前能正常实现需求,如果有其他需求兄弟们可以尝试自己实现,提供思路,勿喷!
1.先自定义一个可以设置最大多少行的FlexboxLayout
class LinesFlexboxLayout @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : FlexboxLayout(context, attrs) {
private var mMaxLines: Int = -1
override fun getFlexLinesInternal(): MutableList<FlexLine> {
return if (mMaxLines == -1) {
super.getFlexLinesInternal()
} else {
val flexLines = super.getFlexLinesInternal();
val size = flexLines.size
if (mMaxLines in 1 until size) {
flexLines.subList(mMaxLines, size).clear();
}
flexLines
}
}
fun setCustomMaxLines(maxLines: Int) {
this.mMaxLines = maxLines
requestLayout()
}
}
2.开始添加flexLayout的子view
binding.flexBoxLayout.setCustomMaxLines(-1)
lifecycleScope.launchWhenStarted {
SearchRecordHelper.getDefault().getSearchRecordsFlow().collect {
val list = it ?: emptyList()
binding.flexBoxLayout.removeAllViews()
list.take(15).forEach { record ->
createBoxLayout(record)
}
viewModel.searchHistoryVisibility.set(list.isNotEmpty())
binding.flexBoxLayout.post {
try {
//这里设定最大行数为3
if (binding.flexBoxLayout.flexLinesInternal.size > 3) {
//获取第三行的FlexLine相关
binding.flexBoxLayout.flexLinesInternal.getOrNull(2)
?.let { thirdLines ->
if (binding.flexBoxLayout.childCount <= 0) {
return@let
}
//获取到upView的宽度,upView就是展开更多记录的按钮view
val measuredWidth = SizeUtils.getMeasuredWidth(upView)
val surplusWidth =
ScreenUtils.getScreenWidth() - thirdLines.mainSize
binding.flexBoxLayout.setCustomMaxLines(3)
//如果剩余距离大于展开按钮的宽度
if (surplusWidth >= measuredWidth) {
//添加展开按钮到第三行的最后一个
binding.flexBoxLayout.addView(
upView,
thirdLines.firstIndex + thirdLines.itemCount
)
//隐藏第三行以外的view
removeOtherView(
thirdLines.firstIndex + thirdLines.itemCount,
binding.flexBoxLayout.childCount
)
} else {
//如果剩余距离小于展开按钮的宽度并且第三行的子view只有一个,修改其宽度确保能放下展开view
if (thirdLines.itemCount == 1) {
val childAt =
binding.flexBoxLayout.getChildAt(thirdLines.firstIndex)
val updateWidth =
ScreenUtils.getScreenWidth() - SizeUtils.dp2px(32f) - SizeUtils.getMeasuredWidth(
upView
)
childAt.updateLayoutParams<ViewGroup.LayoutParams> {
width = updateWidth
height = ViewGroup.LayoutParams.WRAP_CONTENT
}
binding.flexBoxLayout.addView(
upView, thirdLines.firstIndex + thirdLines.itemCount
)
removeOtherView(
thirdLines.firstIndex + thirdLines.itemCount,
binding.flexBoxLayout.childCount)
} else {
//如果剩余距离小于展开按钮的宽度并且第三行的子view有多个,隐藏最后一个,添加
val childAt =
binding.flexBoxLayout.getChildAt(thirdLines.firstIndex + thirdLines.itemCount - 1)
if (childAt != null) {
childAt.isVisible = false
}
binding.flexBoxLayout.addView(
upView,
thirdLines.firstIndex + thirdLines.itemCount - 1
)
removeOtherView(
thirdLines.firstIndex + thirdLines.itemCount - 1,
binding.flexBoxLayout.childCount
)
}
}
}
}
} catch (e: Exception) {
binding.flexBoxLayout.removeAllViews()
}
}
}
}
3.隐藏最大行以外的view
private fun removeOtherView(startIndex: Int, childCount: Int) {
for (index in startIndex + 1 until childCount) {
val childAt = binding.flexBoxLayout.getChildAt(index)
if (childAt != null) {
childAt.isVisible = false
}
}
}