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

新手上路,请多包涵

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

(注意,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 中包含的屏幕上加载一堆视图,然后以编程方式将整个内容滚动到页面顶部,以便用户可以与之交互?

谢谢!

原文由 Glenn 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 424
1 个回答

几年后,唯一合适的解决方案是混合这个线程:

  • 如果没有侦听器或延迟后处理程序,更简单的解决方案将失败,因为可以尝试在 ScrollView 绘制在屏幕上之前滚动,就像@Pelanes 解释的那样
  • 最建议的答案 scan_settings_sv.fullScroll(View.FOCUS_UP); 会将视图移动到第一个可聚焦元素,不一定是滚动视图的顶部。因此,如果有标题或某些文本,或者禁用的视图灰显,并且它们下方有一个 TextView,则 ScrollView 将向上移动到 TextView 而不是 ScrollView Header
  • 就像@Nilhcem 评论的那样,我们需要在最后删除监听器,否则 ScrollView 将继续向上移动
  • 我还使用全局 OnGlobalLayoutListener 引用作为修复编译器警告的方法参数来实现它

所以,最终的解决方案应该实现 view.smoothScrollTo(0,0); ,结合 OnGlobalLayoutListener 确保视图在屏幕上正确显示:

 final ScrollView my_view= dialog.findViewById(R.id.my_view_id);
scan_settings_sv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // Ready, move up
        //my_view.fullScroll(View.FOCUS_UP); //moves up to the to selectable/focusable element
        my_view.smoothScrollTo(0,0); // scrolls to top of view
        my_view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
});

请注意,在调用方法之前获取 ScrollView 非常重要!否则,如果在第一次 final ScrollView my_view= dialog.findViewById(R.id.my_view_id); 调用之后视图高度发生了变化,例如因为 ScrollView 下方的 ListView 被展开,滚动将无法正确到达 ScrollView 的顶部

原文由 user2565854 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题