需求
我们在项目中经常会遇到 tab 页切换的情况,比如通过底部导航栏从 Fragment1
切换到 Fragment2
,这时候有一个需求:Fragment1
里包含了 ScrollView
,并且已经滚动了一部分,要求从 Fragment2
切换回来的时候,Fragment1
滚动到顶部位置。
方案
- 我们很自然的会想到切换
Fragment
会调用onHiddenChanged(boolean hidden)
生命周期,只需要判断!hidden
的时候,执行ScrollView
的scrollTo(x,y)
方法即可:
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
mScrollView.scrollTo(0, 0);
}
}
但是很可惜不能达到项目要求。
- 查看资料发现需要改为:
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
mScrollView.post(new Runnable() {
@Override
public void run() {
mScrollView.scrollTo(0,0);
}
});
}
}
- 经过测试发现如果
Fragment1
中ScrollView
处于滚动状态时就切换到Fragment2
,再切换回来之前的代码依然不起效,这里会很自然的想到加一个延迟效果去,调用View.postDelay()
方法,但是依然不起效。正确的做法是在执行完scrollTo(x,y)
之后再执行smoothScrollTo(x,y)
方法。
@Override
public void onHiddenChanged(boolean hidden) {
super.onHiddenChanged(hidden);
if (!hidden) {
mScrollView.post(new Runnable() {
@Override
public void run() {
mScrollView.scrollTo(0,0);
mScrollView.smoothScrollTo(0, 0);
}
});
}
}
原理
阅读源码后,得知 ScrollView.scrollTo(x,y)
在 Fragment
的 onHiddenChanged(boolean hidden)
生命周期时,还没有计算出滚动条的尺寸,无法正确的 offset 到目的位置。
参考链接
scrollview-scrollto-not-working-saving-scrollview-position-on-rotation
网友评论