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

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

(注意,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)、 scrollDirectionView.FOCUS _ UP 和其他我能想到的所有方法。

因为我没有得到一个错误,我必须假设这些滚动命令实际上是工作的,但是他们滚动到 ListView 的顶部,而不是包含它的 ScrollView 或 RelativeLayout 的顶部。Google 自己对 scrollTo (int x,int y)方法的描述似乎证实了这一点,他们说: “这个版本也将滚动限制在我们孩子的边界内。”.

所以,为了让这个问题更长一些,我该如何在 ScrollView 中加载屏幕上的一系列视图,然后通过编程将整个视图滚动到页面的顶部,以便用户可以与之交互?

谢谢!

185664 次浏览

试试看

mainScrollView.fullScroll(ScrollView.FOCUS_UP);

应该能行。

有同样的问题,可能是某种窃听器。

甚至另一个答案的 fullScroll(ScrollView.FOCUS_UP)也不起作用。
对我来说唯一有效的方法就是在对话框显示之后立即调用 scroll_view.smoothScrollTo(0,0)

我面临同样的问题,当我使用 Scrollview 内视图 Flipper 或对话框,情况下 scrollViewObject.fullScroll(ScrollView.FOCUS_UP)返回假,使情况下 scrollViewObject.smoothScrollTo(0, 0)是为我工作

滚动焦点顶部

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

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

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

    // Wait until my scrollView is ready
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// Ready, move up
scrollView.fullScroll(View.FOCUS_UP);
}
});
runOnUiThread( new Runnable(){
@Override
public void run(){
mainScrollView.fullScroll(ScrollView.FOCUS_UP);
}
}
 final ScrollView scrollview = (ScrollView)findViewById(R.id.selected_place_layout_scrollview);


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

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

listView.setFocusable(false);

很简单

    ScrollView scroll = (ScrollView) findViewById(R.id.addresses_scroll);
scroll.setFocusableInTouchMode(true);
scroll.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
@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);
}

这是 Scrollview的力量卷轴:

            scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.scrollTo(0, 0);
scrollView.pageScroll(View.FOCUS_UP);
scrollView.smoothScrollTo(0,0);
}
});
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// Ready, move up
scrollView.fullScroll(View.FOCUS_UP);
}
});

这招对我很管用

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

我是这样解决我在 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()

此解决方案也适用于 NestedScrollView

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

几年后,唯一合适的解决办法就是混合使用这种思路:

  • 如果没有监听器或后期延迟处理程序,简单的解决方案将失败,因为可以尝试在屏幕上绘制 ScrollView 之前滚动,就像@Pelanes 解释的那样
  • 最建议的答案 scan_settings_sv.fullScroll(View.FOCUS_UP);将移动视图到第一个可聚焦的元素,而不一定是滚动视图的顶部。因此,如果有一个标题或一些文本,或禁用的视图变成了灰色,并且下面有一个 TextView,ScrollView 将移动到 TextView 而不是 ScrollView 标题
  • 像@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 的顶部