我希望ScrollView从底部开始。有什么办法吗?
我希望ScrollView从底部开始。有什么办法吗?
Answers:
scroll.fullScroll(View.FOCUS_DOWN)
也应该工作。
放在一个 scroll.Post(Runnable run)
科特林密码
scrollView.post {
scrollView.fullScroll(View.FOCUS_DOWN)
}
您应该像这样在scroll.post内部运行代码:
scroll.post(new Runnable() {
@Override
public void run() {
scroll.fullScroll(View.FOCUS_DOWN);
}
});
scroll.scrollTo(0, scroll.getHeight());
跳转到底部,或者scroll.smoothScrollTo(0, scroll.getHeight());
滚动更平滑
scrollView.post { scrollView.fullScroll(View.FOCUS_DOWN) }
scroll.fullScroll(View.FOCUS_DOWN)
会导致焦点的改变。当有多个可聚焦视图时(例如两个EditText),这将带来一些奇怪的行为。这个问题还有另一种方式。
View lastChild = scrollLayout.getChildAt(scrollLayout.getChildCount() - 1);
int bottom = lastChild.getBottom() + scrollLayout.getPaddingBottom();
int sy = scrollLayout.getScrollY();
int sh = scrollLayout.getHeight();
int delta = bottom - (sy + sh);
scrollLayout.smoothScrollBy(0, delta);
这很好。
Kotlin扩展
fun ScrollView.scrollToBottom() {
val lastChild = getChildAt(childCount - 1)
val bottom = lastChild.bottom + paddingBottom
val delta = bottom - (scrollY+ height)
smoothScrollBy(0, delta)
}
有时scrollView.post不起作用
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
但是,如果您使用scrollView.postDelayed,它肯定会工作
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
},1000);
最适合我的是
scroll_view.post(new Runnable() {
@Override
public void run() {
// This method works but animates the scrolling
// which looks weird on first load
// scroll_view.fullScroll(View.FOCUS_DOWN);
// This method works even better because there are no animations.
scroll_view.scrollTo(0, scroll_view.getBottom());
}
});
我增加以完美地工作。
private void sendScroll(){
final Handler handler = new Handler();
new Thread(new Runnable() {
@Override
public void run() {
try {Thread.sleep(100);} catch (InterruptedException e) {}
handler.post(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(View.FOCUS_DOWN);
}
});
}
}).start();
}
注意
这个答案是真正旧版android的解决方法。今天,postDelayed
该错误已不再存在,您应该使用它。
postDelayed
:)
我尝试成功了。
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, scrollView.getHeight());
}
}, 1000);
当视图尚未加载时,您将无法滚动。您可以通过上面的发布或睡眠呼叫“稍后”执行此操作,但这不是很优雅。
最好计划滚动并在下一个onLayout()上进行滚动。示例代码在这里:
这是滚动到底部的其他方法
fun ScrollView.scrollToBottom() {
// use this for scroll immediately
scrollTo(0, this.getChildAt(0).height)
// or this for smooth scroll
//smoothScrollBy(0, this.getChildAt(0).height)
// or this for **very** smooth scroll
//ObjectAnimator.ofInt(this, "scrollY", this.getChildAt(0).height).setDuration(2000).start()
}
使用
如果您滚动视图已经布局
my_scroll_view.scrollToBottom()
如果您的滚动视图未完成布局(例如:您在“活动” onCreate
方法中滚动到底部...)
my_scroll_view.post {
my_scroll_view.scrollToBottom()
}
不完全是问题的答案,但是一旦EditText获得焦点,我就需要向下滚动。但是,被接受的答案会使ET也立即失去焦点(我认为是ScrollView)。
我的解决方法如下:
emailEt.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus){
Toast.makeText(getActivity(), "got the focus", Toast.LENGTH_LONG).show();
scrollView.postDelayed(new Runnable() {
@Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
}, 200);
}else {
Toast.makeText(getActivity(), "lost the focus", Toast.LENGTH_LONG).show();
}
}
});
我实际上发现两次调用fullScroll可以达到目的:
myScrollView.fullScroll(View.FOCUS_DOWN);
myScrollView.post(new Runnable() {
@Override
public void run() {
myScrollView.fullScroll(View.FOCUS_DOWN);
}
});
在执行第一次(不成功)滚动之后,可能与激活post()方法有关。我认为在对myScrollView进行任何先前的方法调用之后都会发生此行为,因此您可以尝试用与您相关的任何其他方法替换第一个fullScroll()方法。
为什么scroll.fullScroll(View.FOCUS_DOWN)
甚至无法将其包裹起来也无法工作的一个可能原因.post()
是该视图没有布置。在这种情况下,View.doOnLayout()可能是一个更好的选择:
scroll.doOnLayout(){
scroll.fullScroll(View.FOCUS_DOWN)
}
或者,为勇敢的灵魂做进一步阐述:https://chris.banes.dev/2019/12/03/suspending-views/