android仿QQ列表实现
主要是2个功能
1、列表滑动 当前组名始终在上面显示
2、下拉刷新
在网上找到相似的例子,修改一些以后,加以整合
以下是关键代码部分
1)组名在前面显示
private LinearLayout _groupLayout;public ExpandableListAdapter exAdapter = null; private int _groupIndex = -1; public boolean collapse = false;
@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {firstItemIndex = firstVisibleItem;//this.visibleItemCount = arg2;//visibleLastIndex = firstItemIndex + visibleItemCount - 1;if (exAdapter == null) exAdapter = this.getExpandableListAdapter(); int ptp = view.pointToPosition(0,0); if (ptp != AdapterView.INVALID_POSITION) { UserListView qExlist = (UserListView) view; long pos = qExlist.getExpandableListPosition(ptp); int groupPos = ExpandableListView.getPackedPositionGroup(pos); int childPos = ExpandableListView.getPackedPositionChild(pos); if (groupPos < _groupIndex) { _groupIndex = groupPos; if (_groupLayout != null){ _groupLayout.removeAllViews(); _groupLayout.setVisibility(GONE);//这里设置Gone 为了不让它遮挡后面header } } else if (groupPos >= _groupIndex) { long posNext = qExlist.getExpandableListPosition(ptp+1); int groupPosNext = ExpandableListView.getPackedPositionGroup(posNext); int childPosNext = ExpandableListView.getPackedPositionChild(posNext); final FrameLayout fl = (FrameLayout) getParent(); if(childPosNext < 0) { return; } JDingDebug.printfSystem("index" + _groupIndex + " pos:" + groupPos + " child:" + childPosNext); if(_groupIndex == groupPos && groupPos != 0) { return; } if(groupPos == 0 && childPosNext == 0) { return; } _groupIndex = groupPos; // if (_groupLayout != null) // fl.removeView(_groupLayout); _groupLayout = (LinearLayout)getExpandableListAdapter().getGroupView(groupPos, true, null, null); // JDingDebug.printfSystem("_groupLayout:" + _groupLayout); fl.addView(_groupLayout,fl.getChildCount(), new LayoutParams( LayoutParams.FILL_PARENT, 40)); _groupLayout.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { JDingDebug.printfSystem("按下"); collapseGroup(_groupIndex); new Handler().post(new Runnable() { @Override public void run() { fl.removeViews(1, fl.getChildCount()-1); } }); } }); } } }
2)下拉刷新
private final static int RELEASE_To_REFRESH = 0;private final static int PULL_To_REFRESH = 1;private final static int REFRESHING = 2;private final static int DONE = 3;private final static int LOADING = 4;private boolean isRefreshable;private int firstItemIndex;private boolean isRecored;private int startY;private int state;private boolean isBack;
// 实际的padding的距离与界面上偏移距离的比例private final static int RATIO = 3;private int headContentWidth;private int headContentHeight;private LinearLayout headView;private LayoutInflater inflater;
@Overridepublic boolean onTouchEvent(MotionEvent event) {if (isRefreshable) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:if (firstItemIndex == 0 && !isRecored) {isRecored = true;startY = (int) event.getY();}break;case MotionEvent.ACTION_UP:if (state != REFRESHING && state != LOADING) {if (state == DONE) {// 什么都不做}if (state == PULL_To_REFRESH) {state = DONE;resetHeadView();//changeHeaderViewByState();
//Log.v(TAG, "由下拉刷新状态,到done状态");}if (state == RELEASE_To_REFRESH) {state = REFRESHING;//onRefresh();resetHeadView();}}isRecored = false;isBack = false;break;case MotionEvent.ACTION_MOVE:int tempY = (int) event.getY();if (!isRecored && firstItemIndex == 0) {isRecored = true;startY = tempY;}if (state != REFRESHING && isRecored && state != LOADING) {if (state == RELEASE_To_REFRESH) {setSelection(0);// 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步if (((tempY - startY) / RATIO < headContentHeight)&& (tempY - startY) > 0) {state = PULL_To_REFRESH;//changeHeaderViewByState();
//Log.v(TAG, "由松开刷新状态转变到下拉刷新状态");}// 一下子推到顶了else if (tempY - startY <= 0) {state = DONE;//changeHeaderViewByState();
//Log.v(TAG, "由松开刷新状态转变到done状态");}// 往下拉了,或者还没有上推到屏幕顶部掩盖head的地步else {// 不用进行特别的操作,只用更新paddingTop的值就行了}}// 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态if (state == PULL_To_REFRESH) {setSelection(0);// 下拉到可以进入RELEASE_TO_REFRESH的状态if ((tempY - startY) / RATIO >= headContentHeight) {state = RELEASE_To_REFRESH;isBack = true;//changeHeaderViewByState();//Log.v(TAG, "由done或者下拉刷新状态转变到松开刷新");}// 上推到顶了else if (tempY - startY <= 0) {state = DONE;//changeHeaderViewByState();//Log.v(TAG, "由DOne或者下拉刷新状态转变到done状态");}}// done状态下if (state == DONE) {if (tempY - startY > 0) {state = PULL_To_REFRESH;//changeHeaderViewByState();}}// 更新headView的sizeif (state == PULL_To_REFRESH) {headView.setPadding(0, -1 * headContentHeight+ (tempY - startY) / RATIO, 0, 0);}// 更新headView的paddingTopif (state == RELEASE_To_REFRESH){headView.setPadding(0, (tempY - startY) / RATIO- headContentHeight, 0, 0);}}break;}}return super.onTouchEvent(event);}
public void resetHeadView(){headView.setPadding(0, -1*headContentHeight, 0, 0);state = DONE;}
// 此方法直接照搬自网络上的一个下拉刷新的demo,此处是“估计”headView的width以及heightprivate void measureView(View child) { ViewGroup.LayoutParams p = child.getLayoutParams(); if (p == null) { p = new ViewGroup.LayoutParams( ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width); int lpHeight = p.height; int childHeightSpec; if (lpHeight > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); } else { childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } child.measure(childWidthSpec, childHeightSpec);}
DEMO下载
http://download.csdn.net/detail/ff313976/4504777
更多相关文章
- 关于android全屏截图,无需root,无状态栏,2个方法
- Android设置launchMode为singleTask的Activity怎么刷新页面内容
- Android(安卓)应用开发笔记 - 下拉列表(Spinner)
- 下拉刷新之ScrollView--PullToRefreshScrollView
- 基于Intel x86 Android的RAD游戏开发
- 开关飞行模式
- Android(安卓)Intent.FLAG_ACTIVITY_NEW_TASK的说明
- Android(安卓)fragment生命周期解析
- ColorStateList按钮文字变色