看效果:
配合pullrefresh还能做到下拉刷新,已实现(亲测)。
直接上源码:
/**
* Created by carson on 2017/11/14.
* 实现了分组悬停group header
* @since 1.1.4
*/
public class PinnedExHeaderListview extends ExpandableListView implements AbsListView.OnScrollListener {
private HeaderListener mHeadListener;
/**
* 用于在列表头显示的 View,mHeaderViewVisible 为 true 才可见
*/
private View mHeaderView;
/**
* 列表头是否可见
*/
private boolean mHeaderViewVisible;
private int mHeaderViewWidth;
private int mHeaderViewHeight;
public PinnedExHeaderListview(Context context) {
super(context);
}
public interface HeaderListener {
public static final int PINNED_HEADER_GONE = 0;
public static final int PINNED_HEADER_VISIBLE = 1;
public static final int PINNED_HEADER_PUSHED_UP = 2;
/**
* 获取 Header 的状态
*
* @param groupPosition
* @param childPosition
* @return PINNED_HEADER_GONE, PINNED_HEADER_VISIBLE, PINNED_HEADER_PUSHED_UP
* 其中之一
*/
int getHeaderState(int groupPosition, int childPosition);
/**
* @param header
* @param groupPosition
* @param childPosition
*/
void updateHeader(View header, int groupPosition, int childPosition);
}
public void initHeaderView(View view) {
mHeaderView = view;
if (mHeaderView != null) {
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(lp);
setFadingEdgeLength(0);
}
}
public void setHeaderViewListener(HeaderListener listener) {
this.mHeadListener = listener;
setOnScrollListener(this);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (mHeaderView != null) {
long flatPos = getExpandableListPosition(firstVisibleItem);
int groupPosition = ExpandableListView.getPackedPositionGroup(flatPos);
int childPosition = ExpandableListView.getPackedPositionChild(flatPos);
configureHeaderView(groupPosition, childPosition);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mHeaderView!=null){
int x = (int) ev.getX();
int y = (int) ev.getY();
int pos = pointToPosition(x, y);
if (y >= mHeaderView.getTop() && y <= mHeaderView.getBottom()) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
int groupPosition = getPackedPositionGroup(getExpandableListPosition(pos));
System.out.println("this is :"+ groupPosition +getExpandableListAdapter().getGroup(groupPosition).toString());
if (groupPosition != INVALID_POSITION) {
int point = mHeaderView.getWidth()-x;
if(point< Utils.convertDpToPixel(70)&&point>Utils.convertDpToPixel(15)){
ToastUtil.showMessage("icon click"+groupPosition);
}
// if (isGroupExpanded(groupPosition)) {
// collapseGroup(groupPosition);
// } else {
// expandGroup(groupPosition);
// }
}
}
return true;
}
}
return super.dispatchTouchEvent(ev);
}
private float mDownX;
private float mDownY;
/**
* 如果 HeaderView 是可见的 , 此函数用于判断是否点击了 HeaderView, 并对做相应的处理 , 因为 HeaderView
* 是画上去的 , 所以设置事件监听是无效的 , 只有自行控制 .
*/
// @Override
// public boolean onTouchEvent(MotionEvent ev) {
// if (mHeaderViewVisible) {
// switch (ev.getAction()) {
// case MotionEvent.ACTION_DOWN:
// mDownX = ev.getX();
// mDownY = ev.getY();
// if (mDownX <= mHeaderViewWidth && mDownY <= mHeaderViewHeight) {
// return true;
// }
// break;
// case MotionEvent.ACTION_UP:
// float x = ev.getX();
// float y = ev.getY();
// float offsetX = Math.abs(x - mDownX);
// float offsetY = Math.abs(y - mDownY);
// // 如果 HeaderView 是可见的 , 点击在 HeaderView 内 , 那么触发 headerClick()
// if (x <= mHeaderViewWidth && y <= mHeaderViewHeight
// && offsetX <= mHeaderViewWidth
// && offsetY <= mHeaderViewHeight) {
// if (mHeaderView != null) {
// headerViewClick();
// }
// return true;
// }
// break;
// default:
// break;
// }
// }
// return super.onTouchEvent(ev);
// }
/**
* 点击 HeaderView 触发的事件
*/
private void headerViewClick() {
long packedPosition = getExpandableListPosition(this
.getFirstVisiblePosition());
int groupPosition = ExpandableListView
.getPackedPositionGroup(packedPosition);
this.collapseGroup(groupPosition);
this.setSelectedGroup(groupPosition);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mHeaderView != null) {
measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec);
mHeaderViewWidth = mHeaderView.getMeasuredWidth();
mHeaderViewHeight = mHeaderView.getMeasuredHeight();
}
}
private int mOldState = -1;
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (this.mHeadListener != null) {
long flatPostion = getExpandableListPosition(getFirstVisiblePosition());
int groupPos = ExpandableListView
.getPackedPositionGroup(flatPostion);
int childPos = ExpandableListView
.getPackedPositionChild(flatPostion);
int state = this.mHeadListener.getHeaderState(groupPos, childPos);
if (mHeaderView != null && state != mOldState) {
mOldState = state;
mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
}
configureHeaderView(groupPos, childPos);
}
}
public void configureHeaderView(int groupPosition, int childPosition) {
if (groupPosition == -1 || mHeaderView == null || this.mHeadListener == null || getExpandableListAdapter().getGroupCount() == 0) {
return;
}
int state = mHeadListener.getHeaderState(groupPosition, childPosition);
switch (state) {
case HeaderListener.PINNED_HEADER_GONE: {
mHeaderViewVisible = false;
break;
}
case HeaderListener.PINNED_HEADER_VISIBLE: {
mHeadListener.updateHeader(mHeaderView, groupPosition,
childPosition);
if (mHeaderView.getTop() != 0) {
mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
}
mHeaderViewVisible = true;
break;
}
case HeaderListener.PINNED_HEADER_PUSHED_UP: {
View firstView = getChildAt(0);
int bottom = firstView.getBottom();
// intitemHeight = firstView.getHeight();
int headerHeight = mHeaderView.getHeight();
int y;
if (bottom < headerHeight) {
y = (bottom - headerHeight);
// alpha = MAX_ALPHA * (headerHeight + y) / headerHeight;
} else {
y = 0;
}
mHeadListener.updateHeader(mHeaderView, groupPosition,
childPosition);
if (mHeaderView.getTop() != y) {
mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight
+ y);
}
mHeaderViewVisible = true;
break;
}
}
}
@Override
/**
* 列表界面更新时调用该方法(如滚动时)
*/
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mHeaderViewVisible && mHeaderView != null) {
// 分组栏是直接绘制到界面中,而不是加入到ViewGroup中
drawChild(canvas, mHeaderView, getDrawingTime());
}
}
}
R.layout.item_group_root为分组的view,就是悬停时的view
//support group header floatting
pinnedListview.initHeaderView(getLayoutInflater().inflate(R.layout.item_group_root, groupExpandablelist, false));
pinnedListview.setHeaderViewListener(new PinnedExHeaderListview.HeaderListener() {
@Override
public int getHeaderState(int groupPosition, int childPosition) {
if (groupPosition == -1) {
return PINNED_HEADER_GONE;
}
int childCount = adapter.getChildrenCount(groupPosition);
if (childPosition == childCount - 1) {
return PINNED_HEADER_PUSHED_UP;
} else if (childPosition == -1
&& !pinnedListview.isGroupExpanded(groupPosition)) {
return PINNED_HEADER_GONE;
} else {
return PINNED_HEADER_VISIBLE;
}
}
@Override
public void updateHeader(View header, int groupPosition, int childPosition) {
if (groupPosition > -1) {
TextView group = (TextView) header.findViewById(R.id.root_name);
if (group != null) {
group.setText(adapter.getGroup(groupPosition).getModule_name());
}
}
}
});
本文介绍了一种在Android中实现带有固定头部的ExpandableListView的方法。通过自定义PinnedExHeaderListview类,可以实现在滚动时头部始终可见的效果,并支持下拉刷新功能。
687

被折叠的 条评论
为什么被折叠?



