实现的效果如下图:
红色标注的控件随ListView一起滑动,并能在悬停在顶部导航栏下方。网上关于的Android控件悬停的思路大致如下:给listview添加头部视图headview,在界面布局文件中使用同样的布局dangling覆盖在headview上方,当listview滑动时,根据headview的位置来确定dangling的显示位置,保证dangling能够实时覆盖headview。详见:点击打开链接。
上面的连接中的方法采用滑动距离来确定dangling的显示位置,用在listview中,在listview高速滑动的过程中,容易出现dangling错位,不能准确悬停在导航栏下方的现象。本文的实现思路同上。但在确定dangling位置的时候,采用绝对坐标来确定悬停控件dangling的位置,对上述问题有较好的改善,但不能完全避免。具体做法:
final int h = GetViewCoodinat.getHeight(ll_dangling);
mListView.getViewTreeObserver().addOnScrollChangedListener(
new OnScrollChangedListener() {
@Override
public void onScrollChanged() {
// TODO Auto-generated method stub
mListView.getLocationOnScreen(location_mListView);
ll_static.getLocationOnScreen(location_ll_static);
if (location_ll_static[1] > location_mListView[1]) {
ll_dangling.setY(location_ll_static[1]
- h * 5);
} else {
ll_dangling.setY(location_mListView[1]
- h * 5);
}
}
});
1> 获取dangling控件的高度h
2> 对listviewkongj添加getViewTreeObserver().addOnScrollChangedListener()方法,监听其滚动状态。
3> 在onScrollChanged方法中获取listView和其头部视图headview的坐标。
4>根据坐标进行判断,若headview的Y轴坐标大于listview的竖坐标,则表示dangling控件还没有滑到悬停的位置。则根据headview的坐标设置dangling的坐标。否则,根据listview的坐标设定dangling的坐标。
程序中使用的是绝对坐标,在开始实现的时候,无论怎么设置,dangling控件的位置总是无法与headview重合(这一点我一直没明白原因)。后多次调试,才找到location_ll_static[1] - h * 5这个关系。需要指出,这个关系不是死的,h和常数5并非固定,h与布局文件和屏幕像素的有关,5则是我计算出来的。由于h和屏幕像素关联,这么做在屏幕适配上不会出现问题(我只是在三星S5、小米2S、华为Y300做了适配)。
其实在计算悬空控件dangling的坐标位置时,方法并不通用。我只是在这里阐述一个用绝对坐标实现这个功能的思路。因为用绝对坐标实现,的确可以比较好的解决(并非完全解决)listview告诉滑动时,悬空控件错位的问题。如大家有更好的方法,还需要告诉我。
另外,使用S5做测试时,若长时间进行listview告诉滑动,会出现类似ANR的现象,后台打印错误信息:Surface queueBuffer: error queuing buffer to SurfaceTexture, -22。我没搞清楚原因。