Android修炼之道—可回弹的ListView

来源:互联网 发布:linux配置多个tomcat 编辑:程序博客网 时间:2024/05/22 13:18
。。
添加HeadView和FootView/** * 初始化 */@SuppressWarnings("deprecation")private void init(boolean isHeadViewNeed, boolean isTailViewNeed) {Log.d(TAG, "isHeadViewNeed=" + isHeadViewNeed);Log.d(TAG, "isTailViewNeed=" + isTailViewNeed);if(isHeadViewNeed) {// 监听滚动状态setOnScrollListener(this);// 创建PullListView的HeadViewmHeadView = new View(this.getContext());// 默认白色背景,可以改变颜色, 也可以设置背景图片mHeadView.setBackgroundColor(Color.parseColor("#4F9D9D"));// 默认高度为0mHeadView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.FILL_PARENT, 0));this.addHeaderView(mHeadView);} if(isTailViewNeed) {// 监听滚动状态setOnScrollListener(this);// 创建PullListView的HeadViewmTailView = new View(this.getContext());// 默认白色背景,可以改变颜色, 也可以设置背景图片mTailView.setBackgroundColor(Color.parseColor("#4F9D9D"));// 默认高度为0mTailView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.FILL_PARENT, 0));this.addFooterView(mTailView);}}重写ListView的onTouchEvent事件/** * 覆盖onTouchEvent方法,实现下拉回弹效果 */@SuppressWarnings("deprecation")@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:break;case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP:if (!isRecordPullDown && !isRecordPullUp) {// it's not in pull down state or pull up state, breakLog.d(TAG, "ACTION_UP it's not in pull down state or pull up state, break");break;}if(isPullDownState()) {Log.d(TAG, "isRecordPullDown=" + isRecordPullDown);// 以一定的频率递减HeadView的高度,实现平滑回弹schedulor = Executors.newScheduledThreadPool(1);schedulor.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {mHandler.sendEmptyMessage(PULL_DOWN_BACK_ACTION);}}, 0, PULL_BACK_TASK_PERIOD, TimeUnit.NANOSECONDS);setPullDownState(!isRecordPullDown);} else if(isPullUpState()) {Log.d(TAG, "isRecordPullUp=" + isRecordPullUp);// 以一定的频率递减HeadView的高度,实现平滑回弹schedulor = Executors.newScheduledThreadPool(1);schedulor.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {mHandler.sendEmptyMessage(PULL_UP_BACK_ACTION);}}, 0, PULL_BACK_TASK_PERIOD, TimeUnit.NANOSECONDS);setPullUpState(!isRecordPullUp);}break;case MotionEvent.ACTION_MOVE:Log.d(TAG, "firstItemIndex=" + firstItemIndex);if (!isRecordPullDown && firstItemIndex == 0) {Log.d(TAG, "firstItemIndex=" + firstItemIndex + " set isRecordPullDown=true");startPullDownY = (int) event.getY();setPullType(PULL_DOWN_BACK_ACTION);}else if (!isRecordPullUp && lastItemIndex == getCount()) {Log.d(TAG, "lastItemIndex == getCount()" + " set isRecordPullUp=true");startPullUpY = (int) event.getY();setPullType(PULL_UP_BACK_ACTION);}if (!isRecordPullDown && !isRecordPullUp) {// it's not in pull down state or pull up state, breakLog.d(TAG, "ACTION_MOVE it's not in pull down state or pull up state, break");break;}if(isRecordPullDown) {int tempY = (int) event.getY();int moveY = tempY - startPullDownY;if (moveY < 0) {setPullDownState(false);break;}Log.d(TAG, "tempY=" + tempY);Log.d(TAG, "startPullDownY=" + startPullDownY);Log.d(TAG, "moveY=" + moveY);mHeadView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.FILL_PARENT, (int) (moveY * PULL_FACTOR)));mHeadView.invalidate();} else if(isRecordPullUp) {int tempY = (int) event.getY();int moveY = startPullUpY - tempY;if (moveY < 0) {setPullUpState(false);break;}Log.d(TAG, "tempY=" + tempY);Log.d(TAG, "startPullUpY=" + startPullUpY);Log.d(TAG, "moveY=" + moveY);mTailView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.FILL_PARENT, (int) (moveY * PULL_FACTOR)));mTailView.invalidate();}break;}return super.onTouchEvent(event);}

使用Handler完成HeadView和FootView的回弹效果/** * 实现回弹效果的handler,用于递减HeadView的高度并请求重绘 */@SuppressLint("HandlerLeak")private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch(msg.what) {case PULL_DOWN_BACK_ACTION:AbsListView.LayoutParams headerParams = (LayoutParams) mHeadView.getLayoutParams();// 递减高度headerParams.height -= PULL_BACK_REDUCE_STEP;mHeadView.setLayoutParams(headerParams);// 重绘mHeadView.invalidate();// 停止回弹时递减headView高度的任务if (headerParams.height <= 0) {schedulor.shutdownNow();}break;case PULL_UP_BACK_ACTION:AbsListView.LayoutParams footerParams = (LayoutParams) mTailView.getLayoutParams();// 递减高度footerParams.height -= PULL_BACK_REDUCE_STEP;mTailView.setLayoutParams(footerParams);// 重绘mTailView.invalidate();// 停止回弹时递减headView高度的任务if (footerParams.height <= 0) {schedulor.shutdownNow();}break;}}};

重写ListView的onScroll方法和onScrollStateChanged方法@Overridepublic void onScroll(AbsListView view, int firstVisiableItem,int visibleItemCount, int totalItemCount) {this.firstItemIndex = firstVisiableItem;this.lastItemIndex = firstVisiableItem + visibleItemCount;}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {currentScrollState = scrollState;Log.d(TAG, "scrollState: " + getScrollStateString(currentScrollState));}private String getScrollStateString(int flag) {String str = "";switch(flag) {case OnScrollListener.SCROLL_STATE_IDLE:str = "SCROLL_STATE_IDLE";break;case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:str = "SCROLL_STATE_TOUCH_SCROLL";break;case OnScrollListener.SCROLL_STATE_FLING:str = "SCROLL_STATE_FLING";break;default:str = "wrong state";}return str;}

0 0