我有一个充满多行 TextViews 的 listView。每个 TextView 都有不同数量的文本。按下按钮后,用户将被带到另一个 Activity,他们可以在其中更改字体和字体大小。在重新进入 Fragment 时,如果这些设置已更改,则列表视图将重置,并且 TextView 的测量值也会更改。
在这些设置更改后,我需要知道视图中第一个 TextView 的测量高度。由于某种原因,测量的高度在测量后最初是不同的。一旦我手动滚动列表,就会记录实际的高度测量值。
日志输出:
测量后:电视高度 = 2036
测量后:电视高度 = 2036
滚动后:电视高度 = 7950
最小代码:
class FragmentRead : Fragment() {
private var firstVisiblePos = 0
lateinit var adapterRead: AdapterRead
lateinit var lvTextList: ListView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
lvTextList = view.findViewById(R.id.read_listview)
setListView(lvTextList)
lvTextList.setOnScrollListener(object : AbsListView.OnScrollListener {
var offset = 0
override fun onScrollStateChanged(view: AbsListView, scrollState: Int) {
if(scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
offset = if(lvTextList.getChildAt(0) == null) 0 else lvTextList.getChildAt(0).top - lvTextList.paddingTop
println("After scroll: tv height = ${lvTextList[0].height}")
}
}
override fun onScroll(view: AbsListView, firstVisibleItem: Int, visibleItemCount: Int, totalItemCount: Int) {
firstVisiblePos = firstVisibleItem
}
})
}
/*=======================================================================================================*/
fun setListView(lv: ListView) {
adapterRead = AdapterRead(Data.getTextList(), context!!)
lv.apply {this.adapter = adapterRead}
}
/*=======================================================================================================*/
inline fun <T : View> T.afterMeasured(crossinline f: T.() -> Unit) {
viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
if(measuredWidth > 0 && measuredHeight > 0) {
println("After measured: tv height = ${lvTextList[0].height}")
viewTreeObserver.removeOnGlobalLayoutListener(this)
f()
}
}
})
}
/*=======================================================================================================*/
override fun onStart() {
if(Settings.settingsChanged) {
setListView(lvTextList)
lvTextList.afterMeasured {
println("After measured: tv height = ${lvTextList[0].height}")
}
}
}
}
我试过的:
我尝试使用文本和 layoutParams 设置 TextView 并按照此处的说明读取高度(在渲染到布局之前获取文本视图的高度),但结果是相同的。测量的高度比我滚动列表后要小得多。
我还尝试使用 lvTextList.scrollBy(0,1) 以编程方式滚动列表,以触发滚动侦听器或在读取正确高度时触发其他任何内容。
编辑:回到片段后我延迟了:
Handler().postDelayed({
println("tv height after delay = ${lvScriptureList[0].height}")}, 1000)
这报告了正确的高度。所以我的猜测是 OnGlobalLayoutListener 被提前调用。有任何解决这个问题的方法吗?