将View添加到ScrollView,然后滚动到底部:需要哪个回调?

时间:2015-01-23 08:39:08

标签: android android-layout android-scrollview

在对话框中,我有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完全可见后滚动到底部需要使用哪种回调。

2 个答案:

答案 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"方法

延迟几毫秒然后做你想做的事