在对话框中,我有ScrollView
,其中包含(垂直)LinearLayout
; LinearLayout
中最底部的视图是以TextView
开头的android:visibility="gone"
。
在程序中的某个时刻,我想在setVisiblity(View.VISIBLE)
上TextView
并显示错误消息。并且因为此时ScrollView
可能处于任何位置,所以当出现错误消息时,我想滚动到底部。
我尝试了所有:
scrollView.fullScroll(View.FOCUS_DOWN);
scrollView.scrollTo(0, tvLoginError.getTop());
scrollView.scrollTo(0, tvLoginError.getBottom());
以及每一个中的每一个:
scrollView.post(...)
tvLoginError.post(...)
scrollView.getViewTreeObserver.addOnGlobalLayoutListener(...)
tvLoginError.getViewTreeObserver.addOnGlobalLayoutListener(...)
scrollView.getViewTreeObserver.addOnPreDrawListener(...)
tvLoginError.getViewTreeObserver.addOnPreDrawListener(...)
这些都不正常。当新显示的TextView
位于ScrollView
之外或者当它处于中途可见时,抓取总是停止 - 但从未真正位于底部。 (具有ViewTreeObserver
的那些原则上可以工作,但只有在第一次更新后我没有删除回调。但是如果我把它保持更长时间,我无法知道何时将其删除(... ?)
请告诉我在TextView
完全可见后滚动到底部需要使用哪种回调。
答案 0 :(得分:1)
由于我在寻找答案时发现了这个问题,我想我会保留下一个人的某个时间。
根本问题是您过早地调用scroll
命令。如果向视图添加内容,则在重绘视图之前不会发生布局更改。如果您将content_view.getHeight
写入您正在进行scroll
调用的日志中,您会发现通过添加内容来更改该值。
解决方案是执行以下操作:
scroll_view.post(new Runnable() {
@Override
public void run() {
// Get content_view
scroll_view.smoothScrollTo(content_view.getWidth(), content_view.getHeight());
}
});
这解决了这个问题,因为您要发布到主事件循环,它将在已经排队的事件之后运行 - 包括渲染布局。
注意:我刚刚发现,至少在一个案例中,这没有按预期工作,因为它仍然过早运行post runnable。通过使用短暂的延迟帖子可以很快解决这个问题,但我很想理解为什么上述解决方案并不总是有效。这是一个使用postDelayed的示例(Java 8 lambda版本):
view_port.postDelayed(()->{
LinearLayout content = scroll_view.findViewById(R.id.content);
scroll_view.smoothScrollTo(0, content.getHeight());
}, 200);
答案 1 :(得分:-1)
也许你可以尝试这种方式
使用" postDelayed"方法
延迟几毫秒然后做你想做的事