仿QQ的ListView:SpinnedHeaderExpandableListView实现
来源:互联网 发布:淘宝靠谱的口红代购 编辑:程序博客网 时间:2024/06/11 18:32
最近项目中遇到了可折叠ListView,但是要在滑动过程中有固定Title,方便用户可以点击全选或者收起展开的List的操作。
自定义ListView:
/** * @author fanlitao */public class PinnedHeaderExpandableListView extends ExpandableListView implements OnScrollListener, OnGroupClickListener { public static final int GROUP_COLLAPSE_STATUS = 0; public static final int GROUP_EXPAND_STATUS = 1; public PinnedHeaderExpandableListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); registerListener(); } public PinnedHeaderExpandableListView(Context context, AttributeSet attrs) { super(context, attrs); registerListener(); } public PinnedHeaderExpandableListView(Context context) { super(context); registerListener(); } public interface PinnedSectionedHeaderAdapter { 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; int getSectionHeaderState(int groupPosition, int childPosition); void configureSectionHeader(View header, int groupPosition, int childPosition, int alpha); void setGroupClickStatus(int groupPosition, int status); int getGroupClickStatus(int groupPosition); void onSectionHeaderCheckBoxClick(View header, int groupPosition); } private static final int MAX_ALPHA = 255; private PinnedSectionedHeaderAdapter mAdapter; private View mHeaderView; private boolean mHeaderViewVisible; private int mHeaderViewWidth; private int mHeaderViewHeight; private boolean mGroupEnable = true; public void setSelectionHeaderView(View view) { mHeaderView = view; AbsListView.LayoutParams lp = new AbsListView.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); view.setLayoutParams(lp); if (mHeaderView != null) { setFadingEdgeLength(0); } requestLayout(); } private void registerListener() { setOnScrollListener(this); setOnGroupClickListener(this); } private void headerViewClick() { long packedPosition = getExpandableListPosition(getFirstVisiblePosition()); int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition); if (mAdapter.getGroupClickStatus(groupPosition) == GROUP_EXPAND_STATUS) { collapseGroup(groupPosition); mAdapter.setGroupClickStatus(groupPosition, GROUP_COLLAPSE_STATUS); } else { expandGroup(groupPosition); mAdapter.setGroupClickStatus(groupPosition, GROUP_EXPAND_STATUS); } setSelectedGroup(groupPosition); } private float mDownX; private float mDownY; @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(); int checkbox = OptimUtils.dip2px(getContext(), 100); float offsetX = Math.abs(x - mDownX); float offsetY = Math.abs(y - mDownY); if ((x <= mHeaderViewWidth - checkbox) && y <= mHeaderViewHeight && offsetX <= mHeaderViewWidth && offsetY <= mHeaderViewHeight) { if (mHeaderView != null) { headerViewClick(); } return true; } if ((x > mHeaderViewWidth - checkbox) && y <= mHeaderViewHeight && (offsetX < checkbox) && offsetY <= mHeaderViewHeight) { if (mHeaderView != null) { long packedPosition = getExpandableListPosition(this .getFirstVisiblePosition()); int groupPosition = ExpandableListView .getPackedPositionGroup(packedPosition); mAdapter.onSectionHeaderCheckBoxClick(mHeaderView, groupPosition); } return true; } break; default: break; } } return super.onTouchEvent(ev); } @Override public void setAdapter(ExpandableListAdapter adapter) { super.setAdapter(adapter); mAdapter = (PinnedSectionedHeaderAdapter) adapter; } @Override public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { if (mGroupEnable) { if (mAdapter.getGroupClickStatus(groupPosition) == GROUP_COLLAPSE_STATUS) { mAdapter.setGroupClickStatus(groupPosition, GROUP_EXPAND_STATUS); parent.expandGroup(groupPosition); parent.setSelectedGroup(groupPosition); } else if (mAdapter.getGroupClickStatus(groupPosition) == GROUP_EXPAND_STATUS) { mAdapter.setGroupClickStatus(groupPosition, GROUP_COLLAPSE_STATUS); parent.collapseGroup(groupPosition); } } return true; } public void setGroupClickEnable(boolean state) { mGroupEnable = state; } @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); final long flatPostion = getExpandableListPosition(getFirstVisiblePosition()); final int groupPos = ExpandableListView.getPackedPositionGroup(flatPostion); final int childPos = ExpandableListView.getPackedPositionChild(flatPostion); if (mAdapter != null) { int state = mAdapter.getSectionHeaderState(groupPos, childPos); if (mHeaderView != null && mAdapter != null && state != mOldState) { mOldState = state; mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight); } } configureHeaderView(groupPos, childPos); } public void configureHeaderView(int groupPosition, int childPosition) { if (mHeaderView == null || mAdapter == null || ((ExpandableListAdapter) mAdapter).getGroupCount() == 0) { return; } int state = mAdapter.getSectionHeaderState(groupPosition, childPosition); switch (state) { case PinnedSectionedHeaderAdapter.PINNED_HEADER_GONE: { mHeaderViewVisible = false; break; } case PinnedSectionedHeaderAdapter.PINNED_HEADER_VISIBLE: { mAdapter.configureSectionHeader(mHeaderView, groupPosition, childPosition, MAX_ALPHA); if (mHeaderView.getTop() != 0) { mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight); } mHeaderViewVisible = true; break; } case PinnedSectionedHeaderAdapter.PINNED_HEADER_PUSHED_UP: { View firstView = getChildAt(0); int bottom = firstView.getBottom(); int headerHeight = mHeaderView.getHeight(); int y; int alpha; if (bottom < headerHeight) { y = (bottom - headerHeight); alpha = MAX_ALPHA * (headerHeight + y) / headerHeight; } else { y = 0; alpha = MAX_ALPHA; } mAdapter.configureSectionHeader(mHeaderView, groupPosition, childPosition, alpha); 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) { drawChild(canvas, mHeaderView, getDrawingTime()); } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { final long flatPos = getExpandableListPosition(firstVisibleItem); int groupPosition = ExpandableListView.getPackedPositionGroup(flatPos); int childPosition = ExpandableListView.getPackedPositionChild(flatPos); configureHeaderView(groupPosition, childPosition); } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { }}
需要在这个ListView的Adapter中,实现SpinnedHeaderExpandableListView定义的接口。
以下是Adapter中的部分实现
@Override public int getSectionHeaderState(int groupPosition, int childPosition) { final int childCount = getChildrenCount(groupPosition); if (childPosition == childCount - 1) { return PINNED_HEADER_PUSHED_UP; } else if (childPosition == -1 && !mListView.isGroupExpanded(groupPosition)) { return PINNED_HEADER_GONE; } else { return PINNED_HEADER_VISIBLE; } } @Override public void configureSectionHeader(View header, int groupPosition, int childPosition, int alpha) { TextView headerView = (TextView) header.findViewById(R.id.header_type); ImageView headerIcon = (ImageView) header.findViewById(R.id.junk_icon_header); GroupBean bean = (GroupBean) getGroup(groupPosition); headerView.setText(bean.name); headerIcon.setImageResource(bean.icon); final ImageView checkView = (ImageView) header.findViewById(R.id.checkbox); ImageView expandView = (ImageView) header.findViewById(R.id.expand_icon); expandView.setSelected(bean.isExpand); int size = mChilds.get(groupPosition).size(); if (size == 0) { expandView.setVisibility(View.INVISIBLE); checkView.setVisibility(View.INVISIBLE); } else { checkView.setVisibility(View.VISIBLE); expandView.setVisibility(View.VISIBLE); SparseArray<AppBean> set = mSelectSet.get(groupPosition); if (mIsScanFinished) { checkView.setSelected(set.size() == size); } else { checkView.setSelected(mDefaultCheckState); } } } private HashMap<Integer, Integer> groupStatusMap = new HashMap<Integer, Integer>(); @Override public void setGroupClickStatus(int groupPosition, int status) { groupStatusMap.put(groupPosition, status); } @Override public int getGroupClickStatus(int groupPosition) { if (groupStatusMap.containsKey(groupPosition)) { return groupStatusMap.get(groupPosition); } else { return 0; } }
这样我们就实现了仿QQ的ExpandableListView的效果。虽然还有一些问题,但是大体样子就该是这样。
0 0
- 仿QQ的ListView:SpinnedHeaderExpandableListView实现
- Android仿QQ实现ListView滑动删除
- Android仿QQ实现ListView滑动删除
- ListView自定义Adapter实现仿QQ界面
- 仿qq的listView 滑动删除
- 仿QQ侧滑删除的ListView
- 仿qq界面的实现
- 仿QQ实现ListView中item的左右滑动同时实现ListView的上拉刷新和下拉加载更多
- 实现自定义view(2):仿Android QQ多屏幕显示ListView的效果
- 安卓listView实现下拉刷新上拉加载滑动仿QQ的删除功能
- listview侧滑菜单的实现——高仿QQ联系人列表
- 仿StickyListHeaders 实现listview的header滑动效果(类似QQ好友列表)
- listview侧滑菜单的实现——高仿QQ联系人列表
- 用SlidingMenu实现仿QQ侧滑+Viewpage+ListView多布局
- listview简单实现侧滑删除仿QQ
- ListView仿QQ对话界面
- ListView仿QQ群聊天
- android滑动删除的listview,仿手机QQ的样子
- POJ 2104 K-th Number (可持久化线段树)
- C中printf计算参数时是从右到左压栈的
- 二分查找法的元素查找次数求解
- 研发中版本管理的规范性
- Java 正则式 基础 笔记
- 仿QQ的ListView:SpinnedHeaderExpandableListView实现
- UVA 10934 Dropping water balloons(DP)
- 小z的袜子
- 链表基础程序
- open cv+C++错误及经验总结(十)
- WinNT下Sublime配置Python环境
- Nginx和Apache区别
- crontab 的使用及注意事项
- git学习一