我有一个ChipGroup
小部件来显示标签:
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
...
<com.google.android.material.chip.ChipGroup
android:id="@+id/tags"
android:layout_width="0dp"
android:layout_height="wrap_content"
...
android:theme="@style/Theme.MaterialComponents"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/desc"
app:singleSelection="true"
app:singleLine="false"
app:chipSpacingVertical="@dimen/tag_padding"
/>
...
</androidx.constraintlayout.widget.ConstraintLayout>
标签的数量可以是任何东西,它们的长度可以是任何东西,我想检查ChipGroup
小部件的高度何时超过两行。为了实现这个目标,我需要知道ChipGroup
. 为此,我执行以下操作:
fun displayChips(tagsView: ChipGroup, tagNames: List<String>) {
// вычисление фактической высоты дисплея
val displayWidth = resources.displayMetrics.widthPixels
Log.d(TAG, "displayWidth = $displayWidth")
var chipHeight = 0
var maxChipGroupHeight = 0
val labelCount = tagNames.size
for (i in 0 until labelCount) {
val chip = Chip(tagsView.context)
chip.text = tagNames[i]
// ...
chip.textSize = 14f
chip.maxHeight = 22
if (i == 0) {
// измерение высоты одного тэга
chip.measure(ChipGroup.LayoutParams.WRAP_CONTENT, ChipGroup.LayoutParams.WRAP_CONTENT)
chipHeight = chip.measuredHeight
Log.d(TAG, "chipHeight = $chipHeight")
// измерение высоты двух строк с тэгами (включая расстояние между строками)
maxChipGroupHeight = 2 * chipHeight + resources.getDimensionPixelSize(R.dimen.tag_padding)
Log.d(TAG, "maxChipGroupHeight = $maxChipGroupHeight")
}
tagsView.addView(chip)
// вычисление высоты всего tagsView - НЕ РАБОТАЕТ :(
tagsView.measure(displayWidth, ConstraintLayout.LayoutParams.WRAP_CONTENT)
val tagsViewHeight = tagsView.measuredHeight
Log.d(TAG, "i = $i, tagsViewHeight = $tagsViewHeight")
if (tagsViewHeight > maxChipGroupHeight) {
Log.d(TAG, "i = $i, tagsView height increased two lines")
// ..
}
}
}
作为执行此代码的结果,我得到以下日志:
显示宽度 = 1080
芯片高度 = 96
最大芯片组高度 = 204
i=0,标签视图高度=96
i=1,标签视图高度=96
i=2,标签视图高度=96
i=3,标签视图高度=96
i=4,标签视图高度=96
i=5,标签视图高度=96
尽管标签在屏幕上看起来像这样:
那些。问题是我一直得到相同的高度 tagsView.measuredHeight
(等于 96),尽管它肯定会改变(因为最后有三行带有标签)。我也试过调用方法
tagsView.requestLayout()
tagsView.invalidate()
之前tagsView.measure(...)
,但这并没有改变任何东西。
我将举一个更简单的例子来说明问题的本质。假设有一些应用程序在顶部有一个按钮,在其下方有一个垂直的 LinearLayout。当您单击按钮时,某个对象的副本会添加到布局中,这会更改布局的高度。我们在按钮监听器中放置一个断点,在调试中运行它,看看会发生什么。当行被执行
View v = new View(context);
时,v
高度和宽度将为0,即使它是一个带有文本的按钮。然后将执行该行,layout.addView(v);
但之后高度 v 将保持为 0,以及布局的高度。因为改变对象大小的进程——这些方法 mesure 和 requestLayout 不会立即执行,而是将任务添加到主线程的 Looper 以供它们执行。也就是说,您的所有代码都将首先执行,并且只有在一段时间后布局的大小和位于其中的视图才会改变几乎同样的事情也会发生在你身上。您添加元素并调用 mesure。但它现在没有执行,它在排队,直到你的函数结束才会确定运行。您需要做的:使用 LayoutChangeListener。将其挂在您的 ChipLayout 上,并在每次更改时检查其中的行数。是的,顺便说一句,行数当然可以简单地通过一个数字来获得,而不是通过以像素为单位的高度跳舞=)