我能在Android中以编程方式滚动ScrollView吗?

161

有没有办法以编程方式将 ScrollView 滚动到特定位置?

我创建了一个动态的 TableLayout,它放置在一个 ScrollView 中。因此当发生特定的操作(例如点击按钮等)时,我希望特定行能够自动滚动到顶部位置。

这是可能的吗?

19个回答

214

Pragna的答案并不总是可行的,尝试这个:

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.scrollTo(0, mScrollView.getBottom());
        } 
});
或者
mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.fullScroll(mScrollView.FOCUS_DOWN);
        } 
});

如果您想要滚动到开头

mScrollView.post(new Runnable() { 
        public void run() { 
             mScrollView.fullScroll(mScrollView.FOCUS_UP);
        } 
});

28
我成功地使用了 mScrollView.fullScroll(mScrollView.FOCUS_DOWN); - amcc
3
我可以确认Vanthel的研究结果。在后台任务中使用mScrollView.fullScroll方法可以解决问题。 - AlanKley
1
太好了!确实,没有Runnable它不起作用。现在,它可以工作了! :) - toto_tata
7
如果您想要平滑地滚动,请尝试使用 mScrollView.smoothScrollTo(0, mScrollView.getBottom()); - Mike Ortiz
1
为什么这里需要使用 post - Liuting
显示剩余6条评论

175
ScrollView sv = (ScrollView)findViewById(R.id.scrl);
sv.scrollTo(0, sv.getBottom());

或者

sv.scrollTo(5, 10);


48
结合ercu的回答和评论,最好的方式似乎是:mScrollView.post(new Runnable() { public void run() { mScrollView.fullScroll(View.FOCUS_DOWN); } });(该代码片段用于在Android应用程序中将ScrollView滚动到底部) - sparrowt
2
scrollTo() 不会产生期望的结果。应该使用 fullScroll()。 - Amit Yadav
4
更流畅的滚动效果需要自然的呈现方式:sv.smoothScrollTo(5, 10) - ivan.panasiuk

36

我希望scrollView在onCreateView()之后直接进行滚动(而不是例如点击按钮之后)。为了使其起作用,我需要使用ViewTreeObserver:

mScrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            mScrollView.post(new Runnable() {
                public void run() {
                    mScrollView.fullScroll(View.FOCUS_DOWN);
                }
            });
        }
    });

但请注意,每当某个视图被布局(例如如果您将视图设置为不可见或类似情况)时,这将被调用,因此,请不要忘记使用以下代码删除此侦听器,如果您不再需要它:

public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) 在 SDK 版本 < 16 上

或者

public void removeOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim) 在 SDK 版本 >= 16 上


33
这里有很多好的答案,但我只想补充一点。有时候你需要将ScrollView滚动到布局中的特定视图位置,而不是完全滚动到顶部或底部。
举个简单的例子:在注册表单中,如果用户在表单的编辑文本没有填写完整的情况下点击“注册”按钮,你希望滚动到该特定的编辑文本位置,告诉用户他必须填写该字段。
在这种情况下,你可以这样做:
scrollView.post(new Runnable() { 
        public void run() { 
             scrollView.scrollTo(0, editText.getBottom());
        } 
});

或者,如果您想要平滑滚动而不是瞬间跳转:

scrollView.post(new Runnable() { 
            public void run() { 
                 scrollView.smoothScrollTo(0, editText.getBottom());
            } 
    });

显然,您可以使用任何类型的视图而不是EditText。请注意,getBottom()返回基于其父布局的视图坐标,因此在ScrollView内部使用的所有视图都应仅具有一个父视图(例如LinearLayout)。

如果在ScrollView的子项中有多个父项,则我发现的唯一解决方案是调用父视图上的requestChildFocus:

editText.getParent().requestChildFocus(editText, editText);

但在这种情况下,您无法拥有平滑滚动。

我希望这个答案能帮助到有同样问题的人。


21

可以使用类似这样的东西:

mScrollView.scrollBy(10, 10);
或者
mScrollView.scrollTo(10, 10);

9

9

如果你想要立即滚动到页面的某个位置,可以使用以下方法:

ScrollView scroll= (ScrollView)findViewById(R.id.scroll);
scroll.scrollTo(0, scroll.getBottom());

            OR

scroll.fullScroll(View.FOCUS_DOWN);

            OR

scroll.post(new Runnable() {            
    @Override
    public void run() {
           scroll.fullScroll(View.FOCUS_DOWN);              
    }
});

如果你想要平滑地、缓慢地滚动页面,可以使用以下代码:

private void sendScroll(){
        final Handler handler = new Handler();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {Thread.sleep(100);} catch (InterruptedException e) {}
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        scrollView.fullScroll(View.FOCUS_DOWN);
                    }
                });
            }
        }).start();
    }

那个 catch 块是做什么用的? - John Sardinha
1
Catch块用于在滚动过程中捕获异常,如果发现任何异常。 - Maddy Sharma

5

我已经想出了一些好的解决办法,来滚动到所需的高度。

                scrollView.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        scrollView.scrollBy(0, childView.getHeight());
                    }
                }, 100);

5

可以的。

假设您有一个Layout,里面有很多Views。因此,如果您想以编程方式滚动到任何一个View,则必须编写以下代码段:

例如:

content_main.xml

<ScrollView
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <Button
            android:id="@+id/btn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/txtView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>
</ScrollView>

MainActivity.java

ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
Button btn = (Button) findViewById(R.id.ivEventBanner);
TextView txtView = (TextView) findViewById(R.id.ivEditBannerImage);

如果您想滚动到特定的View,比如说txtview,那么只需写入:

scrollView.smoothScrollTo(txtView.getScrollX(),txtView.getScrollY());

完成了。


4

我已经成功让一个ScrollView(内含一个TextView)滚动到底部:

(我将这段代码放在更新TextView的方法中)

final ScrollView myScrollView = (ScrollView) findViewById(R.id.myScroller);
    myScrollView.post(new Runnable() {
    public void run() {
        myScrollView.fullScroll(View.FOCUS_DOWN);
    }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接