How to write an Android Universal Refresh Control
This article mainly introduces how to write an Android general refresh control, the article is very detailed, has a certain reference value, interested friends must read it!
Train of thought:
Write a RefreshLayout that inherits RelativeLayout
Add a header and tail control as a refresh control
Refresh operation through event distribution
Control the movement of controls through animation
Purpose: to make all its child controls available, even a TextView
Public class RefreshLayout extends RelativeLayout {/ * the speed ratio pulled when sliding the control * / private final int V_REFRESH = 2; / * whether it is a refresh process * true is * false is not * false can only be refreshed * / private boolean mIsRefreshDuring / * you can enter the pull-down refresh * / private boolean mCanDownPull; / * you can pull and refresh * / private boolean mCanUpPull; / * to determine whether the touch is the first time to move * / private boolean mIsFirstMove; / * * the distance of translation of the y axis * / private int mDistanceY / * refresh interface object * / private OnRefresh mOnRefresh; / * variable used to control event interception * / private boolean mCanIntercept; private int mTouchSlop; private int mDistance; private LayoutParams mHeaderParams; private View mHeaderView; private View mFootView; private int mHeaderMaxHeight; private int mStartY; private LayoutParams mFootParams; private int mFootMaxHeight; private PullCallBack mCallBack; private View mChildView Private ObjectAnimator mAnimator; public RefreshLayout (Context context) {super (context); initData ();} public RefreshLayout (Context context, AttributeSet attrs) {super (context, attrs); initData ();} public RefreshLayout (Context context, AttributeSet attrs, int defStyleAttr) {super (context, attrs, defStyleAttr); initData () } / * you must let the interface implemented by the header and tail control * / public interface HeadAndFootCallBack {/ / set the property void setAttribute (); / / start refreshing void startPull (); / / stop refreshing void stopPull () } / * the dragged control subclass must implement * / public interface PullCallBack {boolean canDownPull (); boolean canUpPull ();} private void initData () {/ / cannot draw setWillNotDraw (false) without calling this method. This method must be used after the drop-down refresh is completed * / public void downPullFinish () {mAnimator.setFloatValues (mChildView.getTranslationY (), 0); mAnimator.start (); ((HeadAndFootCallBack) mHeaderView) .stopPull () The method * / public void upPullFinish () {mAnimator.setFloatValues (mChildView.getTranslationY (), 0); mAnimator.start (); ((HeadAndFootCallBack) mFootView) .stopPull () must be called after the pull-up is completed. } / * * automatic drop-down refresh * / public void autoDownPullForHead () {postDelayed (new Runnable () {@ Override public void run () {mCanDownPull = true; mCanUpPull = false; mAnimator.setFloatValues (10, mHeaderMaxHeight); mAnimator.start () ((HeadAndFootCallBack) mHeaderView) .startPull (); mOnRefresh.onDownPullRefresh (); } / * * automatic drop-down refresh * / public void autoUpPullForHead () {postDelayed (new Runnable () {@ Override public void run () {mCanDownPull = false; mCanUpPull = true; mAnimator.setFloatValues (0, mFootMaxHeight); mAnimator.start () ((HeadAndFootCallBack) mFootView) .startPull (); mOnRefresh.onUpPullRefresh ();}}, 500);} @ Override public boolean onInterceptTouchEvent (MotionEvent ev) {return mCanIntercept;} @ Override public boolean onTouchEvent (MotionEvent event) {return true } @ Override public boolean dispatchTouchEvent (MotionEvent event) {Log.e ("shen", "mIsRefreshDuring=" + mIsRefreshDuring); if (mIsRefreshDuring) / * MotionEvent*/ {return super.dispatchTouchEvent (event) will not be obtained if a refresh is in progress } switch (event.getAction ()) {case MotionEvent.ACTION_DOWN: mStartY = (int) event.getY (); initPull (); break; case MotionEvent.ACTION_MOVE: if (event.getPointerCount () = = 1) {int moveY = (int) event.getY () MDistanceY = (moveY-mStartY) / if (! mIsFirstMove & & mDistanceY! = 0 & & mDistanceY
< mTouchSlop) { mCanDownPull = mDistanceY >0; mCanUpPull =! mCanDownPull; mIsFirstMove = true;} if (mCanDownPull & & mCallBack.canDownPull ()) {upDataForDownPull (); / / drop-down refresh mChildView.setEnabled (false); mCanIntercept = true } if (mCanUpPull & & mCallBack.canUpPull ()) {upDataForUpPull (); / / pull-up load mChildView.setEnabled (false); mCanIntercept = true;} mStartY = moveY } break; case MotionEvent.ACTION_UP: mIsRefreshDuring = true; mIsFirstMove = false; if (mHeaderParams.height > = mHeaderMaxHeight) / * can drop down and refresh * / {((HeadAndFootCallBack) mHeaderView) .startPull (); mOnRefresh.onDownPullRefresh () } else if (mFootParams.height > = mFootMaxHeight) / * can pull up and refresh * / {((HeadAndFootCallBack) mFootView) .startPull (); mOnRefresh.onUpPullRefresh ();} else if (mHeaderParams.height > 0 & & mHeaderParams.height)
< mHeaderMaxHeight)/*不能进行下拉刷新,收回*/ { releaseForDownFinished(); } else if (mFootParams.height >0 & & mFootParams.height
< mFootMaxHeight)/*不能进行下拉刷新,收回*/ { releaseForUpFinished(); } else { mIsRefreshDuring = false; mCanIntercept = false; } break; } super.dispatchTouchEvent(event); return true; } /** * 每次进行触摸都需要进行初始化 */ private void initPull() { mCanDownPull = false; mCanUpPull = false; } /** * 不需要进行上拉刷新 */ private void releaseForUpFinished() { mAnimator.setFloatValues(mChildView.getTranslationY(), 0); mAnimator.start(); } /** * 不需要进行下拉刷新 */ private void releaseForDownFinished() { mAnimator.setFloatValues(mChildView.getTranslationY(), 0); mAnimator.start(); } /** * 上拉时处理手势 */ private void upDataForUpPull() { if (mDistanceY != 0) { mFootParams.height -= mDistanceY; if (mFootParams.height = mFootMaxHeight) { mFootParams.height = mFootMaxHeight; } mChildView.setTranslationY(-mFootParams.height); mFootView.requestLayout(); } } /** * 下拉时处理手势 */ private void upDataForDownPull() { if (mDistanceY != 0) { mHeaderParams.height += mDistanceY; if (mHeaderParams.height >= mHeaderMaxHeight) {/ / * mHeaderParams.height = mHeaderMaxHeight;} if (mHeaderParams.height