记录一下这个下拉刷新框架的使用,以后方便再看。
android-Ultra-Pull-To-Refresh是一个功能很强大的下拉刷新框架,比较流行的一个下拉刷新框架。
源码分析:
http://a.codekk.com/detail/Android/Grumoon/android-Ultra-Pull-To-efresh%20%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90
使用步骤:
1、定义xml文件,在里面加入PtrFrameLAyout,然后把需要刷新的视图作为子视图添加进去,子视图支持各种View,包括在内部进行横向滑动的ViewPager等。
2、然后可以在Java代码中setHeaderView或者直接在xml中再添加一个view作为刷新的头部视图。不设置头部view貌似不能下拉。
里面预定义了几个header可以使用,如MaterialHeader。
如果要自定义的话就可以参照里面的进行,只要用实现PtrUIHandler接口的View就行了。
3、然后进行各种设置
有6个参数可配置:
--阻尼系数
默认: 1.7f,越大,感觉下拉时越吃力。
--触发刷新时移动的位置比例
默认,1.2f,移动达到头部高度1.2倍时可触发刷新操作。
--回弹延时
默认 200ms,回弹到刷新高度所用时间
--头部回弹时间
默认1000ms
--刷新是保持头部
默认值 true.
--下拉刷新 / 释放刷新
默认为释放刷新
用xml或者Java设置都可以,如下
mPtrFrame.setResistance(1.7f); mPtrFrame.setRatioOfHeaderHeightToRefresh(1.2f); mPtrFrame.setDurationToClose(200); mPtrFrame.setDurationToCloseHeader(1000); // default is false mPtrFrame.setPullToRefresh(false); // default is true mPtrFrame.setKeepHeaderWhenRefresh(true);
4.再就是处理刷新了。
通过PtrHandler
,可以检查确定是否可以下来刷新以及在合适的时间刷新数据。
ptrFrame.setPtrHandler(new PtrHandler() { @Override public void onRefreshBegin(PtrFrameLayout frame) { frame.postDelayed(new Runnable() { @Override public void run() { ptrFrame.refreshComplete(); } }, 1800); } @Override public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) { // 默认实现,根据实际情况做改动 return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header); } });
注意这句,刷新完成之后要调用refreshComplete(),不然header不会隐藏起来。
5、其它注意的细节
ViewPager滑动冲突: disableWhenHorizontalMove()
长按LongPressed, setInterceptEventWhileWorking()
刷新时,保持内容不动,仅头部下移,
setPinContent()
设置自动刷新(默认开启的)autoRefresh(false/true)进行控制
多指触碰时,会发生跳动,一个解决方法
@Override public boolean dispatchTouchEvent(MotionEvent e) { if (!isEnabled() || mContent == null || mHeaderView == null) { return dispatchTouchEventSupper(e); } dealMulTouchEvent(e); int action = e.getAction(); switch (action) { case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mPtrIndicator.onRelease(); if (mPtrIndicator.hasLeftStartPosition()) { if (DEBUG) { PtrCLog.d(LOG_TAG, "call onRelease when user release"); } onRelease(false); if (mPtrIndicator.hasMovedAfterPressedDown()) { sendCancelEvent(); return true; } return dispatchTouchEventSupper(e); } else { return dispatchTouchEventSupper(e); } case MotionEvent.ACTION_DOWN: mHasSendCancelEvent = false; mPtrIndicator.onPressDown(e.getX(), e.getY()); mScrollChecker.abortIfWorking(); mPreventForHorizontal = false; // The cancel event will be sent once the position is moved. // So let the event pass to children. // fix #93, #102 dispatchTouchEventSupper(e); return true; case MotionEvent.ACTION_MOVE: mLastMoveEvent = e; final int pointerIndex = MotionEventCompat.findPointerIndex(e, mActivePointerId); final float x = MotionEventCompat.getX(e, pointerIndex); final float y = MotionEventCompat.getY(e, pointerIndex); mPtrIndicator.onMove(x, y); // mPtrIndicator.onMove(e.getX(), e.getY()); float offsetX = mPtrIndicator.getOffsetX(); float offsetY = mPtrIndicator.getOffsetY(); if (mDisableWhenHorizontalMove && !mPreventForHorizontal && (Math.abs(offsetX) > mPagingTouchSlop && Math.abs(offsetX) > Math.abs(offsetY))) { if (mPtrIndicator.isInStartPosition()) { mPreventForHorizontal = true; } } if (mPreventForHorizontal) { return dispatchTouchEventSupper(e); } boolean moveDown = offsetY > 0; boolean moveUp = !moveDown; boolean canMoveUp = mPtrIndicator.hasLeftStartPosition(); if (DEBUG) { boolean canMoveDown = mPtrHandler != null && mPtrHandler.checkCanDoRefresh(this, mContent, mHeaderView); PtrCLog.v(LOG_TAG, "ACTION_MOVE: offsetY:%s, currentPos: %s, moveUp: %s, canMoveUp: %s, moveDown: %s: canMoveDown: %s", offsetY, mPtrIndicator.getCurrentPosY(), moveUp, canMoveUp, moveDown, canMoveDown); } // disable move when header not reach top if (moveDown && mPtrHandler != null && !mPtrHandler.checkCanDoRefresh(this, mContent, mHeaderView)) { return dispatchTouchEventSupper(e); } if ((moveUp && canMoveUp) || moveDown) { movePos(offsetY); return true; } } return dispatchTouchEventSupper(e); } /** * http://blog.sina.com.cn/s/blog_8a86f4dd0102whbj.html * https://github.com/liaoinstan/SpringView/blob/master/library/src/main/java/com/liaoinstan/springview/widget/SpringView.java * 处理多点触控的情况,准确地计算Y坐标和移动距离dy * 同时兼容单点触控的情况 */ private int mActivePointerId = MotionEvent.INVALID_POINTER_ID; public void dealMulTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); switch (action) { case MotionEvent.ACTION_DOWN: { final int pointerIndex = MotionEventCompat.getActionIndex(ev); final float x = MotionEventCompat.getX(ev, pointerIndex); final float y = MotionEventCompat.getY(ev, pointerIndex); mPtrIndicator.onPressDown(x, y); mActivePointerId = MotionEventCompat.getPointerId(ev, 0); break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mActivePointerId = MotionEvent.INVALID_POINTER_ID; break; case MotionEvent.ACTION_POINTER_DOWN: { final int pointerIndex = MotionEventCompat.getActionIndex(ev); final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); if (pointerId != mActivePointerId) { final float x = MotionEventCompat.getX(ev, pointerIndex); final float y = MotionEventCompat.getY(ev, pointerIndex); mPtrIndicator.onPressDown(x, y); mActivePointerId = MotionEventCompat.getPointerId(ev, pointerIndex); } break; } case MotionEvent.ACTION_POINTER_UP: { PtrCLog.v(LOG_TAG, "ACTION_POINTER_UP: "); final int pointerIndex = MotionEventCompat.getActionIndex(ev); final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); if (pointerId == mActivePointerId) { final int newPointerIndex = pointerIndex == 0 ? 1 : 0; final float x = MotionEventCompat.getX(ev, pointerIndex); final float y = MotionEventCompat.getY(ev, pointerIndex); mPtrIndicator.onPressDown(x, y); mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); } break; } } }目前只是简单的使用,以后遇到更多细节再添加了。