为了更好的用户体验,当我们使用 ListView 展示列表内容,用户点击进入下级列表后,返回上级时,我们应当给用户返回到上次所在位置
首先你可能会想到使用: void scrollTo(int x, int y) 方法保存 ListView y 位置,
但是实际上,ListView 并不是一个 scroll,你不信可以监听他的滚动事件,x y 参数始终是 0
所以此法不可行
为什么呢?
ListView 原理是创建占据屏幕高度的 View 条数 + 1,当我向上滑动的时候,所有 View y 上移,直到 第一条 View 完全看不到,然后这条 View 就会被移到最后,
此时他不可见,因为到屏幕外去了,当你继续滑动的时候,现在的第一条(相当于原始的第二条)逐渐滚出屏幕,原先的第一条(现在是最后一条),就从屏幕底部出现,
填补空白,这就是我们在 Adapter 里要使用 View Holder 的原因,所有的 View 是循环利用的
以此类推,所以不管你有多少内容,ListView 始终只有占据屏幕高度的 View 条数,
不能理解的自己仔细琢磨琢磨
下面我来讲实现》
你可能注意到,ListView 有一个方法:
void setSelection(int position)
void setSelectionFromTop(int position, int y)
意思是是 position 位置的内容显示在 ListView 第一条,就是使 ListView 滚动到 position 的意思,实际上你调用这个方法的时候他并没有滚动过程,而是直接到
而:setSelection(int position) 相当于 setSelectionFromTop(position, 0)
所以我们在进入下级内容之前,保存当前第一条 View 的 position 即可,如何获取这个 position 呢
使用:int getFirstVisiblePosition() 这个方法
然后返回上级的时候,再取出 position ,使用 setSelection 方法即可恢复位置,如图所示:
假如你没发现这2张图有什么区别,下面的内容也不用看了,
当然如果你细心一点你会发现,.estrings 目录的位置有点偏差,对的,因为 setSelection() 默认设置第一条 view 在顶端位置,
当然做到这一步其实用户很难察觉有什么不一样,
但是如果追求完美,你就像恢复到原模原样,怎么办,还有一个 setSelectionFromTop 方法嘛
那这个 y 怎么获取呢,
ListView.getChildAt(0).getTop()
意思就是第一条 View 的 y 位置嘛