【问题标题】:How to scroll to top of long ScrollView layout?如何滚动到长 ScrollView 布局的顶部?
【发布时间】:2011-05-06 09:19:17
【问题描述】:

对于我的应用程序的一部分,用户会看到一个名称列表,并要求用户按照他们认为合适的方式对它们进行分组。

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

所以,为了让一个更长的问题变得更长,我如何在 ScrollView 中包含的屏幕上加载一堆视图,然后以编程方式将整个内容滚动到页面顶部,以便用户可以与之交互?

谢谢!

【问题讨论】:

    标签: android listview scrollview


    【解决方案1】:

    我在 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()
    

    【讨论】:

      【解决方案2】:

      此解决方案也适用于 NestedScrollView

      NestedScrollView nestedScrollView = view.findViewById(R.id.YourNestedScrollViewID);
      nestedScrollView.fullScroll(ScrollView.FOCUS_UP);
      

      【讨论】:

        【解决方案3】:

        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);
            }
        });
        

        【讨论】:

        • 我正在处理滚动视图应该滚动到页面底部的相同问题,将其修复!
        • View 对象提供了一个 post(Runnable) 方法,您可以使用该方法,而不是猜测“神奇”x 您必须等待的毫秒数,该方法将在小部件在 UI 上呈现后发布可运行对象.
        • @Ryan : post(Runnable) 在 Nexus 5 (Genymotion) 上对我总是不起作用
        • post(Runnable) 可能不起作用,因为如果您在视图膨胀步骤之后获取数据,则首先向上滚动工作,然后数据填充到视图中。所以你要么你应该使用 postDelayed(Runnable,dummyMillis) 要么你应该在数据填充过程之后使用 scroll.fullScroll(ScrollView.FOCUS_UP)。
        • 您提供静态毫秒的第一个解决方案是一种糟糕的方法。
        【解决方案4】:

        这对我有用

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

        【讨论】:

          【解决方案5】:
          scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
              @Override
              public void onGlobalLayout() {
                  // Ready, move up
                  scrollView.fullScroll(View.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);
                            }
                        });
            

            【讨论】:

              【解决方案7】:
              @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);
                  }
              

              【讨论】:

              • 这肯定会运行,
              • 请简要说明此答案如何解决问题。
              【解决方案8】:

              很简单

                  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,嗨,你把这些写在你的 xml 文件中了吗?我发现这只适用于onCreate()
              • @imknownJ.Kimu 在 xml 文件中为我工作
              • 这对我有用。您需要第二行和第三行。它不适用于我的 XML。
              • 如果可以,我会吻你!在这上面花了 1-2 个小时。等待两个列表视图加载并且不想专注于它们时最好的一个。将其添加到 onResume() 中。
              【解决方案9】:

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

              listView.setFocusable(false);
              

              【讨论】:

              • 这也是 gridviews 的正确解决方案。当您在同一视图组中有多个视图元素时会发生这种情况,尤其是列表或网格视图顶部的另一个列表视图。由于适配器通知 UI 线程,视图被重新创建并向上滚动到第一个元素。只需调用 listView.setFocusable(false) / gridView.setFocusable(false)。如果您从 xml 文件中执行此操作,则将无法正常工作。
              • 这个解决方案也适用于我的情况,我在 NestedScrollView 中有 RecyclerView,所以它会自动向下滚动。谢谢,伙计!
              • 我必须在设置适配器之前添加它,但之后就像一个魅力。谢谢
              • 完美解释!!
              • 感谢 Miguel 和特别是 omersem 的解释,特别是关于如果在 XML 中设置它将如何工作的部分,这让我有些头疼
              【解决方案10】:
               final ScrollView scrollview = (ScrollView)findViewById(R.id.selected_place_layout_scrollview);
              
                       scrollview.post(new Runnable() { 
                              public void run() { 
                                  scrollview.scrollTo(0, 0); 
                              } 
                          }); 
              

              【讨论】:

                【解决方案11】:
                runOnUiThread( new Runnable(){
                   @Override
                   public void run(){
                      mainScrollView.fullScroll(ScrollView.FOCUS_UP);
                   }
                }
                

                【讨论】:

                  【解决方案12】:

                  试试

                  mainScrollView.fullScroll(ScrollView.FOCUS_UP);
                  

                  它应该可以工作。

                  【讨论】:

                  • 也适合我。 :D
                  • 我发现 ScrollView#fullScroll() 改变了当前焦点。我用 EditText 测试过。
                  【解决方案13】:

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

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

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

                  【讨论】:

                  • 不错的解决方案 - 不要忘记在 onGlobalLayout 方法调用 scrollView.getViewTreeObserver().removeOnGlobalLayoutListener(this); 结束时删除全局侦听器
                  【解决方案14】:

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

                  Scroll Focus Top

                  【讨论】:

                    【解决方案15】:

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

                    即使来自其他答案的fullScroll(ScrollView.FOCUS_UP) 也不起作用。
                    唯一对我有用的是在显示对话框后立即调用scroll_view.smoothScrollTo(0,0)

                    【讨论】:

                    • 这最初是可行的,但后来当我一次又一次地尝试这样做时,这种方法并没有给出令人满意的结果。
                    • 我从 scroll_view.smoothScrollTo(0,0) 解决,当我们在滚动视图旁边有 listview 时 fullScroll(ScrollView.FOCUS_UP) 将不起作用。
                    • scroll_view.smoothScrollTo(0,0) 对我来说比 mainScrollView.fullScroll(ScrollView.FOCUS_UP);谢谢!
                    • 在大多数设备上 fullScroll(ScrollView.FOCUS_UP) 工作,但在 Nexus 5 和我的文本大小调高的设备上 - fullSscroll 在操作栏下移动,smoothScrollTo(0,0) 工作在所有设备上都更好。
                    • 这也比fullScroll() 具有优势,因为它在移动后保持所选项目仍然处于选中状态。使用fullScroll(),在我的情况下,每次都会重新选择滚动视图中的第一项,与滚动向上移动之前的选定项目无关。
                    猜你喜欢
                    • 2020-01-04
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2023-04-09
                    • 2016-10-28
                    • 1970-01-01
                    相关资源
                    最近更新 更多