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


162

对于我的应用程序的一部分,系统会向用户显示一个名称列表,并要求他们将其分组为合适的名称。

(请注意,ListView代码是从Android Views教程中逐字复制的。我尚未根据需要对其进行自定义,我只是想弄清楚如何实现此功能。)

基本布局是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的顶部。谷歌自己对“ scrollTo(int x,int y)”方法的描述似乎证实了这一点,他们说“此版本还将滚动限制在我们孩子的范围之内。”。

因此,要提出一个更长的问题,我如何在ScrollView中包含的屏幕上加载一堆视图,然后以编程方式将整个视图滚动到页面顶部,以便用户可以与之交互?

谢谢!

Answers:


264

尝试

mainScrollView.fullScroll(ScrollView.FOCUS_UP);

它应该工作。


也为我工作。:D
Muntasir Aonik '17

1
我发现ScrollView#fullScroll()更改了当前焦点。我用EditText进行了测试。
illusionJJ

175

遇到相同的问题,可能是某种错误。

即使fullScroll(ScrollView.FOCUS_UP)来自其他答案,也没有用。 对话框显示后,
只有对我有用的东西才打电话scroll_view.smoothScrollTo(0,0)


此方法最初有效,但是后来当我尝试一次又一次地执行此操作时,此方法未获得令人满意的结果。
JaydeepW

16
我从scroll_view.smoothScrollTo(0,0)解决,当我们在侧面有listview时,scrollview当时的fullScroll(ScrollView.FOCUS_UP)将无法工作。
Kirtikumar A.

1
scroll_view.smoothScrollTo(0,0)对我来说比mainScrollView.fullScroll(ScrollView.FOCUS_UP)更好。谢谢!
marienke 2014年

2
在大多数设备上,fullScroll(ScrollView.FOCUS_UP)都可以工作,但是在Nexus 5和我将文本大小调大的设备上-将fullSscroll移动到了操作栏下,smoothScrollTo(0,0)在所有设备上的工作效果都更好。
jt-gilkeson

这样做还有一个好处fullScroll(),就是在移动后仍保持选中的项目不变。使用fullScroll(),在我的情况下,每次滚动视图中的第一项都会被重新选择,而与滚动向上移动之前的选定项无关。
GeertVc

97

我有同样的问题,并解决了它。希望对您有帮助。

listView.setFocusable(false);

3
这也是网格视图的正确解决方案。当同一视图组中有多个视图元素时,尤其是列表或gridview顶部的另一个listview时,就会发生这种情况。由于适配器会通知UI线程,因此将重新创建视图并向上滚动到第一个元素。只需调用listView.setFocusable(false)/ gridView.setFocusable(false)。如果您从xml文件中执行此操作,则它将无法正常运行。
omersem '16

此解决方案在我的情况下也适用,我在NestedScrollView中装有RecyclerView,因此它可以自动向下滚动。谢啦!
Nilesh Rathore

在设置适配器之前,我必须添加此设置,但是在此之后它就像一个魅力。谢谢
社区

完美的解释!
BorjaLópez,

谢谢米格尔(Miguel)尤其是omersem的解释,尤其是有关如果在XML中设置它将如何工作的部分,这使我省去了一些麻烦
buradd

53

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应该滚动到页面底部,将其正确修复!
机器部落2014年

1
View对象提供了post(Runnable)方法供您使用,该方法可以在widget在UI上渲染后发布可运行对象,而不用猜测您必须等待的“神奇” x毫秒数。
瑞安

@Ryan:post(Runnable)在Nexus 5(Genymotion)上始终对我不起作用
Dika

post(Runnable)可能不起作用,因为如果您在视图浮动步骤之后获取数据,则首先进行滚动工作,然后将数据填充到视图中。因此,您应该在数据填充过程之后使用postDelayed(Runnable,dummyMillis)或使用scroll.fullScroll(ScrollView.FOCUS_UP)。
oguzhan

您第一个使用静态毫秒数的解决方案是一种不好的方法。
Malwinder Singh

35

所有这些有效解决方案的主要问题是,当尚未在屏幕上绘制滚动条时,您试图将其向上移动。

您需要等待直到屏幕上出现滚动视图,然后使用这些解决方案中的任何一种将其上移。这比后延迟更好,因为您不介意延迟。

    // 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 2014年

30

好简单

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

3
对我来说,它不起作用(第三行),解决方案是:scroll.fullScroll(View.FOCUS_UP); (包括您的前2行)
medskill

@medskill,您好,您是否在xml文件中编写了这些代码?我认为这仅适用于onCreate()
不知名的'17

@ imknownJ.Kimu在xml文件中为我工作
Paglian

这对我有用。您需要第二行和第三行。对我来说,它在XML中不起作用。
美国东部时间

2
如果可以的话,我会吻你!花了1-2个小时。当等待两个列表视图加载并且不希望专注于它们时,最好的一个。将其添加到onResume()。
约翰·T

24

我在View Flipper或Dialog中使用Scrollview时遇到相同的问题,该案例 scrollViewObject.fullScroll(ScrollView.FOCUS_UP)返回false,因此该案例 scrollViewObject.smoothScrollTo(0, 0)对我有效

滚动焦点顶部


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

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

9
runOnUiThread( new Runnable(){
   @Override
   public void run(){
      mainScrollView.fullScroll(ScrollView.FOCUS_UP);
   }
}


6

这是scrollview的强制滚动:

            scrollView.post(new Runnable() {
                @Override
                public void run() {
                    scrollView.scrollTo(0, 0);
                    scrollView.pageScroll(View.FOCUS_UP);
                    scrollView.smoothScrollTo(0,0);
                }
            });

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

1

我这样在Kotlin中修复了问题:

scrollview.isFocusableInTouchMode = true
scrollview.fullScroll(View.FOCUS_UP)
scrollview.smoothScrollTo(0,0)

0
@SuppressWarnings({ "deprecation", "unchecked" })
public void swipeTopToBottom(AppiumDriver<MobileElement> driver) 
                    throws InterruptedException {
       Dimension dimensions = driver.manage().window().getSize();
        Double screenHeightStart = dimensions.getHeight() * 0.30;
        int scrollStart = screenHeightStart.intValue();
        System.out.println("s="+scrollStart);
        Double screenHeightEnd = dimensions.getHeight()*0.90;
        int scrollEnd = screenHeightEnd.intValue();
        driver.swipe(0,scrollStart,0,scrollEnd,2000);
        CommonUtils.threadWait(driver, 3000);
    }

这将确保运行
Ajeet Gour

请提供有关此答案如何解决问题的简要说明。
AyberkÖzgür17年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.