package com.lcodecore.tkrefreshlayout.processor;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.View;
import com.lcodecore.tkrefreshlayout.TwinklingRefreshLayout;
import com.lcodecore.tkrefreshlayout.utils.ScrollingUtil;
/**
* Created by lcodecore on 2017/3/1.
*/
//TODO FullOverScrollDecorator、VerticalDecorator
public class OverScrollDecorator extends Decorator {
//主要为了监测Fling的动作,实现越界回弹
private float mVelocityY;
//满足越界的手势的最低速度(默认3000)
private static final int OVER_SCROLL_MIN_VX = 3000;
//针对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次
public OverScrollDecorator(TwinklingRefreshLayout.CoContext processor, IDecorator decorator1) {
super(processor, decorator1);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return decorator != null && decorator.dispatchTouchEvent(ev);
}
@Override
public boolean interceptTouchEvent(MotionEvent ev) {
return decorator != null && decorator.interceptTouchEvent(ev);
}
@Override
public boolean dealTouchEvent(MotionEvent e) {
return decorator != null && decorator.dealTouchEvent(e);
}
private boolean preventTopOverScroll = false;
private boolean preventBottomOverScroll = false;
private boolean checkOverScroll = false;
@Override
public void onFingerDown(MotionEvent ev) {
if (decorator != null) decorator.onFingerDown(ev);
preventTopOverScroll = ScrollingUtil.isViewToTop(cp.getTargetView(), cp.getTouchSlop());
preventBottomOverScroll = ScrollingUtil.isViewToBottom(cp.getTargetView(), cp.getTouchSlop());
}
@Override
public void onFingerUp(MotionEvent ev, boolean isFling) {
if (decorator != null) {
decorator.onFingerUp(ev, checkOverScroll && isFling);
}
checkOverScroll = false;
}
@Override
public void onFingerScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY, float velocityX, float velocityY) {
if (decorator != null)
decorator.onFingerScroll(e1, e2, distanceX, distanceY, velocityX, velocityY);
}
@Override
public void onFingerFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (decorator != null) decorator.onFingerFling(e1, e2, velocityX, velocityY);
//fling时才触发OverScroll,获取速度并采用演示策略估算View是否滚动到边界
if (!cp.enableOverScroll()) return;
int dy = (int) (e2.getY() - e1.getY());
if (dy < -cp.getTouchSlop() && preventBottomOverScroll) return;//控件滚动在底部且向上fling
if (dy > cp.getTouchSlop() && preventTopOverScroll) return;//控件滚动在顶部且向下fling
mVelocityY = velocityY;
if (Math.abs(mVelocityY) >= OVER_SCROLL_MIN_VX) {
mHandler.sendEmptyMessage(MSG_START_COMPUTE_SCROLL);
checkOverScroll = true;
} else {
mVelocityY = 0;
cur_delay_times = ALL_DELAY_TIMES;
}
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
int mTouchSlop = cp.getTouchSlop();
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.getTargetView();
if (cp.allowOverScroll()) {
if (mVelocityY >= OVER_SCROLL_MIN_VX) {
if (ScrollingUtil.isViewToTop(mChildView, mTouchSlop)) {
cp.getAnimProcessor().animOverScrollTop(mVelocityY, cur_delay_times);
mVelocityY = 0;
cur_delay_times = ALL_DELAY_TIMES;
}
} else if (mVelocityY <= -OVER_SCROLL_MIN_VX) {
if (ScrollingUtil.isViewToBottom(mChildView, mTouchSlop)) {
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;
}
}
};
}