整理以前的代码,发现一个带浮动层ExpandableListView,(这段代码好像是照着github上的一个开源组件写的,忘了地址了,如有冒犯,请联系本人删除)记录核心代码:
private int tempY = 0;
/**记录listView滚动的距离*/
private int lastTop = 0;
mListView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
if(scrollState == OnScrollListener.SCROLL_STATE_IDLE){
if (mListView.getChildAt(0) != null) {
lastTop = -mListView.getChildAt(0).getTop() + mListView.getFirstVisiblePosition() * mListView.getChildAt(0).getHeight();
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
if (mListView.getChildAt(0) != null) {
int currentTop = -mListView.getChildAt(0).getTop() + mListView.getFirstVisiblePosition() * mListView.getChildAt(0).getHeight();
/*以Item的高度为参考来判断当前移动的距离是否触发隐藏或显示底部栏操作*/
int offsetTop = currentTop - lastTop;
if(null != MainActivity.MainContext && MainActivity.MainContext.isBarShow() && offsetTop > mListView.getChildAt(0).getHeight()){
/*隐藏*/
if(null != MainActivity.lastFragment && MainActivity.lastFragment.equals(CoursesFragment.this)){
MainActivity.MainContext.hideBar();
}
}else if(null != MainActivity.MainContext && !MainActivity.MainContext.isBarShow() && offsetTop < -mListView.getChildAt(0).getHeight()){
/*显示*/
MainActivity.MainContext.showBar();
}
}
if(!mPullToRefreshView.isAnimFinished()){
return;
}
/*在下拉状态释放后,对headerView进行最后的隐藏*/
if(mPullToRefreshView.isReadyForPullDown()){
headerView.setVisibility(View.GONE);
return;
}
/*当前处于上拉或下拉状态,则直接返回*/
if(mPullToRefreshView.isBeingDragged()){
return;
}
int firstPos = view.pointToPosition(0, 0);// 其实就是firstVisibleItem
if (firstPos == AdapterView.INVALID_POSITION)// 如果第一个位置值无效
return;
long firstPackedPos = mListView.getExpandableListPosition(firstPos);
int firstChildPos = ExpandableListView.getPackedPositionChild(firstPackedPos);// 获取第一行child的id
int firstGroupPos = ExpandableListView.getPackedPositionGroup(firstPackedPos);// 获取第一行group的id
if((firstGroupPos == AdapterView.INVALID_POSITION
|| !mListView.isGroupExpanded(firstGroupPos))
&& firstChildPos == AdapterView.INVALID_POSITION){
/*显示出来的第一个item既不是group也不是child,这时应该是header,隐藏indicatorGroup*/
headerView.setVisibility(View.GONE);
return;
}else if(firstChildPos == AdapterView.INVALID_POSITION){
/*显示出来的第一个item是group, 取其高度,用来初始化indicatorGroupHeight*/
headerViewHeight = mListView.getChildAt(0).getHeight();
headerView.setVisibility(View.VISIBLE);
}else{
headerView.setVisibility(View.VISIBLE);
}
if (headerViewHeight == 0) {
return;
}
if(firstGroupPos != AdapterView.INVALID_POSITION){
if (firstGroupPos != headerViewPos) {// 如果指示器显示的不是当前group
refreshHeaderViewData(firstGroupPos);
headerViewPos = firstGroupPos;
}
}
/**
* calculate point (0,indicatorGroupHeight) 下面是形成往上推出的效果
*/
int topOffset = headerViewHeight;
int secondPos = mListView.pointToPosition(0, headerViewHeight + mListView.getDividerHeight());// 第二个item的位置
if (secondPos == AdapterView.INVALID_POSITION)//如果无效直接返回
return;
long secondPackedPos = mListView.getExpandableListPosition(secondPos);
int secondGroupPos = ExpandableListView.getPackedPositionGroup(secondPackedPos);//获取第二个group的id
if (secondGroupPos != AdapterView.INVALID_POSITION && secondGroupPos != headerViewPos) {//如果不等于指示器当前的group
topOffset = mListView.getChildAt(secondPos - mListView.getFirstVisiblePosition()).getTop();
}
tempY = (headerViewHeight - topOffset) + mPullToRefreshView.getScrollY();
if(tempY < 0){
tempY = 0;
}
// headerView.scrollTo(0, tempY);
MarginLayoutParams layoutParams = (MarginLayoutParams) headerView
.getLayoutParams();
layoutParams.topMargin = -(tempY + mPullToRefreshView.getScrollY());
headerView.setLayoutParams(layoutParams);
}
});
}
至于布局文件就不贴了,简单说明:浮动层和ExpandableListView同在一个RelativeLayout中,并且浮动层浮在ExpandableListView的上面,(浮动层的顶部和ExpandableListView的顶部在同一位置,且浮动层的布局和ExpandableListView的布局相同);
注:这种实现方式比较简单,但是效率低,滑动流畅度不太好;看到有人是使用Google联系人中的组件实现这种效果,效果要好很多,有兴趣的同学可以找一下看看!
Gradle引用方式:
compile 'com.itz:FloatExpandableListView:1.0.0'