package com.example.administrator.cookman.ui.component.twinklingrefreshlayout; import android.os.Handler; import android.os.Message; import android.support.v7.widget.RecyclerView; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.webkit.WebView; import android.widget.AbsListView; import com.example.administrator.cookman.ui.component.twinklingrefreshlayout.utils.ScrollingUtil; /** * Created by lcodecore on 2016/11/26. */ public class OverScrollProcessor { private TwinklingRefreshLayout.CoProcessor cp; //满足越界的手势的最低速度(默认3000) protected int OVER_SCROLL_MIN_VX = 3000; public OverScrollProcessor(TwinklingRefreshLayout.CoProcessor coProcessor) { this.cp = coProcessor; mTouchSlop = cp.getTouchSlop(); } private VelocityTracker moveTracker; private int mPointerId; private float vy; public void init() { final View mChildView = cp.getContent(); final GestureDetector gestureDetector = new GestureDetector(cp.getContext(), new GestureDetector.SimpleOnGestureListener() { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (cp.isRefreshVisible() && distanceY >= mTouchSlop && !cp.isOpenFloatRefresh()) { cp.setRefreshing(false); cp.getAnimProcessor().animHeadHideByVy((int) vy); } if (cp.isLoadingVisible() && distanceY <= -mTouchSlop) { cp.setLoadingMore(false); cp.getAnimProcessor().animBottomHideByVy((int) vy); } return super.onScroll(e1, e2, distanceX, distanceY); } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (!cp.enableOverScroll()) return false; mVelocityY = velocityY; // if (!(mChildView instanceof AbsListView || mChildView instanceof RecyclerView)) { //既不是AbsListView也不是RecyclerView,由于这些没有实现OnScrollListener接口,无法回调状态,只能采用延时策略 if (Math.abs(mVelocityY) >= OVER_SCROLL_MIN_VX) { mHandler.sendEmptyMessage(MSG_START_COMPUTE_SCROLL); } else { mVelocityY = 0; cur_delay_times = ALL_DELAY_TIMES; } // } return false; } }); mChildView.setOnTouchListener(new View.OnTouchListener() { int mMaxVelocity = ViewConfiguration.get(cp.getContext()).getScaledMaximumFlingVelocity(); @Override public boolean onTouch(View v, MotionEvent event) { //手势监听的两个任务:1.监听fling动作,获取速度 2.监听滚动状态变化 obtainTracker(event); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mPointerId = event.getPointerId(0); break; case MotionEvent.ACTION_UP: moveTracker.computeCurrentVelocity(1000, mMaxVelocity); vy = moveTracker.getYVelocity(mPointerId); releaseTracker(); break; case MotionEvent.ACTION_CANCEL: releaseTracker(); break; } return gestureDetector.onTouchEvent(event); } }); if (!cp.enableOverScroll()) return; if (mChildView instanceof AbsListView) { ((AbsListView) mChildView).setOnScrollListener(new AbsListView.OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (cp.allowOverScroll() && firstVisibleItem == 0 || ((AbsListView) mChildView).getLastVisiblePosition() == totalItemCount - 1) { if (mVelocityY >= OVER_SCROLL_MIN_VX && ScrollingUtil.isAbsListViewToTop((AbsListView) mChildView)) { cp.getAnimProcessor().animOverScrollTop(mVelocityY, cur_delay_times); mVelocityY = 0; cur_delay_times = ALL_DELAY_TIMES; } if (mVelocityY <= -OVER_SCROLL_MIN_VX && ScrollingUtil.isAbsListViewToBottom((AbsListView) mChildView)) { cp.getAnimProcessor().animOverScrollBottom(mVelocityY, cur_delay_times); mVelocityY = 0; cur_delay_times = ALL_DELAY_TIMES; } } } }); } else if (mChildView instanceof RecyclerView) { ((RecyclerView) mChildView).addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (cp.allowOverScroll() && newState == RecyclerView.SCROLL_STATE_IDLE) { if (mVelocityY >= OVER_SCROLL_MIN_VX && ScrollingUtil.isRecyclerViewToTop((RecyclerView) mChildView)) { cp.getAnimProcessor().animOverScrollTop(mVelocityY, cur_delay_times); mVelocityY = 0; cur_delay_times = ALL_DELAY_TIMES; } if (mVelocityY <= -OVER_SCROLL_MIN_VX && ScrollingUtil.isRecyclerViewToBottom((RecyclerView) mChildView)) { cp.getAnimProcessor().animOverScrollBottom(mVelocityY, cur_delay_times); mVelocityY = 0; cur_delay_times = ALL_DELAY_TIMES; } } super.onScrollStateChanged(recyclerView, newState); } }); } } private void obtainTracker(MotionEvent event) { if (null == moveTracker) { moveTracker = VelocityTracker.obtain(); } moveTracker.addMovement(event); } private void releaseTracker() { if (null != moveTracker) { moveTracker.clear(); moveTracker.recycle(); moveTracker = null; } } //主要为了监测Fling的动作,实现越界回弹 private float mVelocityY; //针对部分没有OnScrollListener的View的延时策略 private static final int MSG_START_COMPUTE_SCROLL = 0; //开始计算 private static final int MSG_CONTINUE_COMPUTE_SCROLL = 1;//继续计算 private static final int MSG_STOP_COMPUTE_SCROLL = 2; //停止计算 private int cur_delay_times = 0; //当前计算次数 private static final int ALL_DELAY_TIMES = 60; //10ms计算一次,总共计算20次 private int mTouchSlop; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_START_COMPUTE_SCROLL: cur_delay_times = -1; //这里没有break,写作-1方便计数 case MSG_CONTINUE_COMPUTE_SCROLL: cur_delay_times++; View mChildView = cp.getContent(); if (!(mChildView instanceof AbsListView || mChildView instanceof RecyclerView)) { if (cp.allowOverScroll() && mVelocityY >= OVER_SCROLL_MIN_VX && (mChildView != null && Math.abs(mChildView.getScrollY()) <= 2 * mTouchSlop)) { cp.getAnimProcessor().animOverScrollTop(mVelocityY, cur_delay_times); mVelocityY = 0; cur_delay_times = ALL_DELAY_TIMES; } if (cp.allowOverScroll() && mVelocityY <= -OVER_SCROLL_MIN_VX && mChildView != null) { if (mChildView instanceof WebView) { WebView webview = (WebView) (mChildView); if (Math.abs(webview.getContentHeight() * webview.getScale() - (webview.getHeight() + webview.getScrollY())) <= 2 * mTouchSlop) { cp.getAnimProcessor().animOverScrollBottom(mVelocityY, cur_delay_times); mVelocityY = 0; cur_delay_times = ALL_DELAY_TIMES; } } else if (mChildView instanceof ViewGroup) { View subChildView = ((ViewGroup) mChildView).getChildAt(0); if (subChildView != null && subChildView.getMeasuredHeight() <= mChildView.getScrollY() + mChildView.getHeight()) { //滚动到了底部 cp.getAnimProcessor().animOverScrollBottom(mVelocityY, cur_delay_times); mVelocityY = 0; cur_delay_times = ALL_DELAY_TIMES; } } else if (mChildView.getScrollY() >= mChildView.getHeight()) { cp.getAnimProcessor().animOverScrollBottom(mVelocityY, cur_delay_times); mVelocityY = 0; cur_delay_times = ALL_DELAY_TIMES; } } } if (cur_delay_times < ALL_DELAY_TIMES) mHandler.sendEmptyMessageDelayed(MSG_CONTINUE_COMPUTE_SCROLL, 10); break; case MSG_STOP_COMPUTE_SCROLL: cur_delay_times = ALL_DELAY_TIMES; break; } } }; }