我有一个扩展了LinearLayout并实现了onMeasure的自定义视图。我希望子视图可以根据需要设置宽度,或者填充可用空间。
XML文件:
父视图:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.myapplication.AtMostLinearLayout
android:id="@+id/at_most_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
按钮示例:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_delete" />
</FrameLayout>
视图可以通过编程方式添加,例如:
findViewById<AtMostLinearLayout>(R.id.at_most_linear_layout).apply {
repeat(4) {
LayoutInflater.from(context).inflate(R.layout.button, this)
}
}
最后是自定义视图类:
class AtMostLinearLayout @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : LinearLayout(context, attrs, defStyle) {
private val maxTotalWidth = context.resources.getDimensionPixelOffset(R.dimen.max_buttons_width)
init {
orientation = HORIZONTAL
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if (childCount < 1) return
val newWidth = min(measuredWidth, maxTotalWidth)
var availableWidth = newWidth
var numberOfLargeChildren = 0
repeat(childCount) {
getChildAt(it).let { child ->
if (child.measuredWidth > availableWidth / childCount) {
availableWidth -= child.measuredWidth
numberOfLargeChildren++
}
}
}
val minChildWidth = availableWidth / max(childCount - numberOfLargeChildren, 1)
repeat(childCount) {
getChildAt(it).apply {
measure(
MeasureSpec.makeMeasureSpec(max(measuredWidth, minChildWidth), EXACTLY),
UNSPECIFIED
)
}
}
setMeasuredDimension(
makeMeasureSpec(newWidth, EXACTLY), makeMeasureSpec(measuredHeight, EXACTLY))
}
}
在从左到右的情况下它工作得很好: 但是在从右到左的情况下,视图会因为某些原因偏移并且绘制在了ViewGroup的外部:
这个偏移可能来自哪里?看起来子元素的测量调用被添加到了该部分中,或者至少加了一半…
onLayout
中接收到的左侧位置超过了Viewgroup的一半。我似乎无法弄清楚这个左侧位置是在哪里计算的。 - Novae