笔者之前在做一个项目的时候,需要实现一个特殊效果的布局,即列表顶部的布局能“下拉悬停”,也就是说,当列表往上滑动的时候,列表顶部的布局,能悬停在屏幕顶部,而不被滑出屏幕。
如图所示:当列表滑动时,搜索框也能随着滑动,然而搜索框无论如何却不会滑出布局之外,而是能悬停在顶部。
原理很简单,其实,搜索框布局一直都是随着列表滑动的,只是,当搜索框布局滑动到屏幕上边缘时,意味着该布局即将被挡住,这时候及时在布局顶部添加一个一模一样的布局(笔者称为替代布局),覆盖了原来的布局,所以,原先的搜索框布依旧就会被滑出布局外,然而由于替代布局至于布局顶部,所以会产生其该布局总是顶再屏幕上方的错觉。
笔者在下图中显示了布局边界,希望可以帮助各位更清晰地描述这一点。
所以这里就要解决一个问题:
如何知道搜索框布局在什么时候即将滑出屏幕边缘?
首次,笔者发现,在ListView,中,有个addHeaderView(View v) 方法,该方法可以让使用者添加任意特殊的View到ListView的顶部成为特殊的列表项,使得该特殊的View可以随着ListView的列表项一起滑动,并且可以添加多了列表项。笔者在demo中,就把搜索框布局通过该方法添加到ListView的顶部,使其成为ListView的列表项。这样做的好处是什么,答案在下面:
其次,我们可以为ListView注册滑动监听器:
ListView listView;
//.....
listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
这样就可以得到listView滑动时的一些信息了,比如:第二个回调函数onScroll(),只要ListView处于滑动状态,就会被不断调用,这个函数方有三个参数,重点是第二个参数:firstVisibleItem, 该参数记录了该ListView当前第一个可视的列表项是第几个,所以根据这个参数就得知某个列表项是否可视,所以搜索框布局成为ListView的列表项后,就能知道搜索框是否被屏幕顶部遮住,假设搜索框布局的位置为position,那么可能的情况是:
1.如果firstVisibleItem < position,,则搜索框布局没有被遮住;
2.如果firstVisibleItem >= position,,则搜索框布局即将或者已经被布局顶部遮住,这时就要把替代布局显示出来,
所以大概的实现原理就是这样:
让搜索框布局成为ListView的列表项,实时监测搜索框布局的位置,并在其将被遮挡的时候显示出替代布局。
下面看看代码吧:
首先看布局文件:
//first_layout.xml,用于显示顶部的图片而已
<?xml version="1.0" encoding="utf-8"?>
<