【发布时间】:2021-02-23 19:51:51
【问题描述】:
我有一个充满多行 TextView 的 listView。每个 TextView 都有不同数量的文本。按下按钮后,用户将被带到另一个 Activity,他们可以在其中更改字体和字体大小。在重新进入 Fragment 时,如果这些设置发生了变化,则 listView 将被重置,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 并按照此处 (Getting height of text view before rendering to layout) 的说明读取高度,但结果是相同的。测得的高度比我滚动列表后要小很多。
我还尝试使用 lvTextList.scrollBy(0,1) 以编程方式滚动列表,以触发滚动侦听器或在读取正确高度时触发其他任何内容。
编辑:回到片段后我延迟了:
Handler().postDelayed({
println("tv height after delay = ${lvScriptureList[0].height}")}, 1000)
这会报告正确的高度。所以我的猜测是 OnGlobalLayoutListener 被提前调用。有什么办法解决这个问题?
【问题讨论】:
标签: android listview scroll textview ongloballayoutlistener