如何滚动到较长的ScrollView布局的顶部?

179
对于我的应用程序的一部分,用户将看到一个名称列表,并被要求按照他们自己的意愿对其进行分组。
(请注意,ListView 代码是从 Android 视图教程中直接复制的。我还没有根据我的需求自定义它,我只是在尝试弄清楚如何使其工作。)
基本布局是一个 LinearLayout,其中包含一个 ScrollView(在下面的代码中称为“groupsScrollView”),其中包含一个 RelativeLayout。 我有一些按钮和文本,然后是我的 ListView,在其下方显示名称列表。 所有这些都比可见屏幕区域更高,因此允许用户垂直滚动以查看所有内容。
这一切都运行良好,除了当页面加载时,它总是预先滚动到我的 ListView 顶部 - 即页面的中间。 我创建的告诉用户该怎么做的文本和按钮不可见。
我可以抓住屏幕并向上滚动,那样就可以正常工作,但我希望屏幕在已经滚动到顶部的情况下加载。 用户不应该需要向上滚动才能看到新加载页面的顶部。 但是,我尝试的一切编程滚动到屏幕顶部的方法都失败了。
这是我的 onCreate 方法:
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.groups);

    mainScrollView = (ScrollView)findViewById(R.id.groupsScrollView);

    //get the Bundle out of the Intent...
    Bundle extras = getIntent().getExtras();
    mNames = extras.getStringArray("mNames");

    setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, mNames));

    ListView lv = getListView();
    lv.setTextFilterEnabled(true);

    //This is the line I'm having issues with
    mainScrollView.pageScroll(View.FOCUS_UP);

    lv.setOnItemClickListener(new OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View view,
            int position, long id) {
          // When clicked, show a toast with the TextView text
          Toast.makeText(getApplicationContext(), ((TextView) view).getText(),
              Toast.LENGTH_SHORT).show();
        }
      });
}

"mainScrollView.pageScroll(View.FOCUS_UP);"这一行代码存在问题。它不会导致错误,但似乎没有起到任何作用。我尝试过使用"scrollTo(0,0)"、"scrollDirection(View.FOCUS_UP)"以及其他我能想到的所有方法。

由于我没有收到错误提示,我必须假设这些滚动命令实际上有效,但它们将滚动到ListView的顶部,而不是包含它的ScrollView或RelativeLayout的顶部。Google关于"scrollTo(int x,int y)"方法的描述似乎证实了这一点,其中他们说:“此版本还将滚动限制在我们的子级边界内。”

因此,长话短说,我该如何在屏幕上加载一堆视图,这些视图包含在ScrollView中,然后通过编程方式将整个视图滚动到页面顶部,以便用户可以与之交互?

谢谢!

18个回答

288

请尝试

mainScrollView.fullScroll(ScrollView.FOCUS_UP);

它应该能够工作。


对我来说也可以。 :D - Muntasir Aonik
1
我发现ScrollView#fullScroll()会改变当前的焦点。我已经用EditText测试过了。 - illusionJJ

183

我有同样的问题,可能是某种错误。

即使使用其他答案中的 fullScroll(ScrollView.FOCUS_UP) 也无法解决问题。
对我有效的唯一方法是在对话框显示后立即调用scroll_view.smoothScrollTo(0,0)


这最初是有效的,但后来当我尝试再次做同样的事情时,这种方法并没有给出令人满意的结果。 - JaydeepW
16
我解决了从scroll_view.smoothScrollTo(0,0)开始的问题,当我们在ScrollView中有ListView时,fullScroll(ScrollView.FOCUS_UP)将无法工作。 - Kirtikumar A.
1
scroll_view.smoothScrollTo(0,0) 对我来说比 mainScrollView.fullScroll(ScrollView.FOCUS_UP) 更好用;谢谢! - marienke
2
在大多数设备上,fullScroll(ScrollView.FOCUS_UP)可以正常工作,但在Nexus 5和我将文本大小调整到最大的设备上,fullSscroll会移动到操作栏下方,smoothScrollTo(0,0)在所有设备上都能更好地工作。 - jt-gilkeson
这种方法相比于fullScroll()的优点在于,它可以在移动后保持所选项目仍然被选中。而使用fullScroll()时,在我的情况下,每次滚动向上时都会重新选择滚动视图中的第一个项目,而不考虑滚动前所选的项目。 - GeertVc
如果您不想使用scroll_view.smoothScrollTo(0,0),可以尝试scroll_view.scrollTo(0,0),这也是有效的。 - DarkPh03n1X

100

我曾经遇到同样的问题,这个方法解决了它。

listView.setFocusable(false);

3
这也适用于网格视图的正确解决方法。当您在同一视图组中拥有多个视图元素时,尤其是在列表或网格视图顶部另一个列表视图时,就会发生这种情况。由于适配器通知UI线程,视图会被重新创建并滚动到第一个元素。只需调用listView.setFocusable(false) / gridView.setFocusable(false)。如果您在xml文件中这样做,它将不起作用。 - omersem
这个解决方案在我的情况下也起作用了,我在NestedScrollView中有RecyclerView,所以它会自动向下滚动。谢谢,伙计! - Nilesh Rathore
1
我必须在设置适配器之前添加这个,但之后它就像魔法般地工作了。谢谢。 - Community
完美的解释!! - Borja López
谢谢Miguel和omersem的解释,尤其是有关XML设置不起作用的部分,这节省了我很多麻烦。 - buradd

59

scrollViewObject.fullScroll(ScrollView.FOCUS_UP) 代码本身没有问题,但是会存在一个问题: 在 scrollViewObject 中的数据填充完毕之前这行代码会被立即调用。因此,您需要等待一些毫秒直到数据填充完成。您可以尝试使用以下代码:

scrollViewObject.postDelayed(new Runnable() {
    @Override
    public void run() {
        scroll.fullScroll(ScrollView.FOCUS_UP);
    }
}, 600);

 scrollViewObject.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        scrollViewObject.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        scrollViewObject.fullScroll(View.FOCUS_UP);
    }
});

我曾经遇到过同样的问题,即ScrollView应该滚动到页面底部,但我已经解决了它! - Machine Tribe
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Ryhan
@Ryan:在Nexus 5(Genymotion)上,post(Runnable)对我总是不起作用。 - Dika
post(Runnable) 可能无法正常工作,因为如果在视图膨胀步骤之后获取数据,则首先向上滚动,然后将数据填充到视图中。因此,您应该使用 postDelayed(Runnable,dummyMillis) 或在数据填充过程之后使用 scroll.fullScroll(ScrollView.FOCUS_UP)。 - oguzhan
你的第一个解决方案,即给出静态毫秒数的方法是不好的。 - Malwinder Singh

36

所有这些有效解决方案的主要问题是,您试图在它尚未显示在屏幕上时向上滚动滚动视图。

您需要等待滚动视图显示在屏幕上,然后使用任何一种解决方案将其向上移动。这比使用postdelay更好,因为您不用担心延迟。

    // Wait until my scrollView is ready
    scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            // Ready, move up
            scrollView.fullScroll(View.FOCUS_UP);
        }
    });

7
不错的解决方案 - 不要忘记在调用onGlobalLayout方法结束时移除全局监听器scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this); - Nilhcem

30

非常容易

    ScrollView scroll = (ScrollView) findViewById(R.id.addresses_scroll);
    scroll.setFocusableInTouchMode(true);
    scroll.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);

4
对我来说它没有起作用(第三行),解决方法是:scroll.fullScroll(View.FOCUS_UP);(包括前两行)。 - medskill
@medskill,你好,这些是你在xml文件中编写的吗?我发现这只在onCreate()中起作用。 - imknown
@imknownJ.Kimu 在 XML 文件中对我有效。 - Paglian
这对我有用。你需要第二和第三行。在我的XML中它不起作用。 - E.T.
2
如果可以的话,我会亲吻你!花了1-2个小时在这上面。等待两个列表视图加载时最好的方法,不想关注它们。将其添加到onResume()中。 - John T

25

当我在View Flipper或对话框中使用ScrollView时,遇到了相同的问题,此时scrollViewObject.fullScroll(ScrollView.FOCUS_UP)返回false,因此可以使用scrollViewObject.smoothScrollTo(0, 0)来解决问题。

滚动到顶部


22
 final ScrollView scrollview = (ScrollView)findViewById(R.id.selected_place_layout_scrollview);

         scrollview.post(new Runnable() { 
                public void run() { 
                    scrollview.scrollTo(0, 0); 
                } 
            }); 

13

这对我有用

scroll_view.smoothScrollTo(0,0); // scroll to top of screen

11
我用 Kotlin 解决了我的问题,方法如下:
scrollview.isFocusableInTouchMode = true
scrollview.fullScroll(View.FOCUS_UP)
scrollview.smoothScrollTo(0,0)

您也可以创建这样的扩展:

ScrollView.moveToTop()
{
    this.isFocusableInTouchMode = true
    this.fullScroll(View.FOCUS_UP)
    this.smoothScrollTo(0,0)
}

并像这样使用:

scrollView.moveToTop()

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