Skip to content

Commit 352000c

Browse files
committed
完成带装饰模式的重构,Refresh为原业务,OverScroll为装饰
1 parent b3cb4ad commit 352000c

File tree

10 files changed

+392
-19
lines changed

10 files changed

+392
-19
lines changed

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

library/src/main/java/com/lcodecore/tkrefreshlayout/AnimProcessor.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,18 @@
1414
* Created by lcodecore on 2016/11/26.
1515
*/
1616

17-
public class AnimProcessor {
17+
class AnimProcessor implements IAnimRefresh, IAnimOverScroll {
1818

1919
private TwinklingRefreshLayout.CoProcessor cp;
2020
private static final float animFraction = 1f;
2121
//动画的变化率
2222
private DecelerateInterpolator decelerateInterpolator;
2323

24-
public AnimProcessor(TwinklingRefreshLayout.CoProcessor coProcessor) {
24+
AnimProcessor(TwinklingRefreshLayout.CoProcessor coProcessor) {
2525
this.cp = coProcessor;
26-
2726
decelerateInterpolator = new DecelerateInterpolator(8);
2827
}
2928

30-
public void init() {
31-
}
32-
33-
3429
public void scrollHeadByMove(float moveY) {
3530
float offsetY = decelerateInterpolator.getInterpolation(moveY / cp.getMaxHeadHeight() / 2) * moveY / 2;
3631
if (cp.getHeader().getVisibility() != VISIBLE) cp.getHeader().setVisibility(VISIBLE);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.lcodecore.tkrefreshlayout;
2+
3+
/**
4+
* Created by lcodecore on 2017/3/3.
5+
*/
6+
7+
public abstract class Decorator implements IDecorator {
8+
protected IDecorator decorator;
9+
protected TwinklingRefreshLayout.CoProcessor cp;
10+
11+
public Decorator(TwinklingRefreshLayout.CoProcessor processor, IDecorator decorator1) {
12+
cp = processor;
13+
decorator = decorator1;
14+
}
15+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.lcodecore.tkrefreshlayout;
2+
3+
/**
4+
* Created by lcodecore on 2017/3/3.
5+
*/
6+
7+
public interface IAnimOverScroll {
8+
void animOverScrollTop(float vy, int computeTimes);
9+
void animOverScrollBottom(float vy, int computeTimes);
10+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.lcodecore.tkrefreshlayout;
2+
3+
/**
4+
* Created by lcodecore on 2017/3/3.
5+
*/
6+
7+
public interface IAnimRefresh {
8+
void scrollHeadByMove(float moveY);
9+
void scrollBottomByMove(float moveY);
10+
void animHeadToRefresh();
11+
void animHeadBack();
12+
void animHeadHideByVy(int vy);
13+
void animBottomToLoad();
14+
void animBottomBack();
15+
void animBottomHideByVy(int vy);
16+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.lcodecore.tkrefreshlayout;
2+
3+
import android.view.MotionEvent;
4+
5+
/**
6+
* Created by lcodecore on 2017/3/1.
7+
*/
8+
9+
public interface IDecorator {
10+
boolean interceptTouchEvent(MotionEvent ev);
11+
12+
boolean dealTouchEvent(MotionEvent ev);
13+
14+
boolean onFingerScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY, float velocityY);
15+
16+
boolean onFingerFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
17+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package com.lcodecore.tkrefreshlayout;
2+
3+
import android.os.Handler;
4+
import android.os.Message;
5+
import android.view.MotionEvent;
6+
import android.view.View;
7+
8+
import com.lcodecore.tkrefreshlayout.utils.ScrollingUtil;
9+
10+
/**
11+
* Created by lcodecore on 2017/3/1.
12+
*/
13+
//TODO FullOverScrollDecorator、VerticalDecorator
14+
public class OverScrollDecorator extends Decorator {
15+
16+
//主要为了监测Fling的动作,实现越界回弹
17+
private float mVelocityY;
18+
19+
//满足越界的手势的最低速度(默认3000)
20+
private static final int OVER_SCROLL_MIN_VX = 3000;
21+
22+
//针对View的延时策略
23+
private static final int MSG_START_COMPUTE_SCROLL = 0; //开始计算
24+
private static final int MSG_CONTINUE_COMPUTE_SCROLL = 1;//继续计算
25+
private static final int MSG_STOP_COMPUTE_SCROLL = 2; //停止计算
26+
27+
private int cur_delay_times = 0; //当前计算次数
28+
private static final int ALL_DELAY_TIMES = 60; //10ms计算一次,总共计算20次
29+
30+
public OverScrollDecorator(TwinklingRefreshLayout.CoProcessor processor, IDecorator decorator1) {
31+
super(processor, decorator1);
32+
}
33+
34+
35+
@Override
36+
public boolean interceptTouchEvent(MotionEvent ev) {
37+
return decorator!=null && decorator.interceptTouchEvent(ev);
38+
}
39+
40+
@Override
41+
public boolean dealTouchEvent(MotionEvent e) {
42+
return decorator!=null && decorator.dealTouchEvent(e);
43+
}
44+
45+
@Override
46+
public boolean onFingerScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY, float velocityY) {
47+
return decorator!=null && decorator.onFingerScroll(e1,e2,distanceX,distanceY,velocityY);
48+
}
49+
50+
@Override
51+
public boolean onFingerFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
52+
if (decorator!=null) decorator.onFingerFling(e1,e2,velocityX,velocityY);
53+
//fling时才触发OverScroll,获取速度并采用演示策略估算View是否滚动到边界
54+
if (!cp.enableOverScroll()) return false;
55+
mVelocityY = velocityY;
56+
if (Math.abs(mVelocityY) >= OVER_SCROLL_MIN_VX) {
57+
mHandler.sendEmptyMessage(MSG_START_COMPUTE_SCROLL);
58+
} else {
59+
mVelocityY = 0;
60+
cur_delay_times = ALL_DELAY_TIMES;
61+
}
62+
return false;
63+
}
64+
65+
private Handler mHandler = new Handler() {
66+
67+
@Override
68+
public void handleMessage(Message msg) {
69+
int mTouchSlop = cp.getTouchSlop();
70+
switch (msg.what) {
71+
case MSG_START_COMPUTE_SCROLL:
72+
cur_delay_times = -1; //这里没有break,写作-1方便计数
73+
case MSG_CONTINUE_COMPUTE_SCROLL:
74+
cur_delay_times++;
75+
76+
//TODO Content改为TargetView
77+
View mChildView = cp.getContent();
78+
79+
if (cp.allowOverScroll()) {
80+
if (mVelocityY >= OVER_SCROLL_MIN_VX) {
81+
if (ScrollingUtil.isViewToTop(mChildView, mTouchSlop)) {
82+
cp.getAnimProcessor().animOverScrollTop(mVelocityY, cur_delay_times);
83+
mVelocityY = 0;
84+
cur_delay_times = ALL_DELAY_TIMES;
85+
}
86+
} else if (mVelocityY <= -OVER_SCROLL_MIN_VX) {
87+
if (ScrollingUtil.isViewTopBottom(mChildView, mTouchSlop)) {
88+
cp.getAnimProcessor().animOverScrollBottom(mVelocityY, cur_delay_times);
89+
mVelocityY = 0;
90+
cur_delay_times = ALL_DELAY_TIMES;
91+
}
92+
}
93+
}
94+
95+
//计算未超时,继续发送消息并循环计算
96+
if (cur_delay_times < ALL_DELAY_TIMES)
97+
mHandler.sendEmptyMessageDelayed(MSG_CONTINUE_COMPUTE_SCROLL, 10);
98+
break;
99+
case MSG_STOP_COMPUTE_SCROLL:
100+
cur_delay_times = ALL_DELAY_TIMES;
101+
break;
102+
}
103+
}
104+
};
105+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.lcodecore.tkrefreshlayout;
2+
3+
import android.view.MotionEvent;
4+
5+
import com.lcodecore.tkrefreshlayout.utils.ScrollingUtil;
6+
7+
/**
8+
* Created by lcodecore on 2017/3/1.
9+
*/
10+
11+
public class RefreshDecorator implements IDecorator {
12+
13+
protected TwinklingRefreshLayout.CoProcessor cp;
14+
15+
public RefreshDecorator(TwinklingRefreshLayout.CoProcessor processor) {
16+
if (processor == null) throw new NullPointerException("The coprocessor can not be null.");
17+
cp = processor;
18+
}
19+
20+
private float mTouchX, mTouchY;
21+
22+
@Override
23+
public boolean interceptTouchEvent(MotionEvent ev) {
24+
switch (ev.getAction()) {
25+
case MotionEvent.ACTION_DOWN:
26+
mTouchX = ev.getX();
27+
mTouchY = ev.getY();
28+
break;
29+
case MotionEvent.ACTION_MOVE:
30+
float dx = ev.getX() - mTouchX;
31+
float dy = ev.getY() - mTouchY;
32+
if (Math.abs(dx) <= Math.abs(dy)) {//滑动允许最大角度为45度
33+
if (dy > 0 && !ScrollingUtil.canChildScrollUp(cp.getScrollableView()) && cp.allowPullDown()) {
34+
cp.setStatePTD();
35+
return true;
36+
} else if (dy < 0 && !ScrollingUtil.canChildScrollDown(cp.getScrollableView()) && cp.allowPullUp()) {
37+
cp.setStatePBU();
38+
return true;
39+
}
40+
}
41+
break;
42+
}
43+
return false;
44+
}
45+
46+
@Override
47+
public boolean dealTouchEvent(MotionEvent e) {
48+
if (cp.isRefreshVisible() || cp.isLoadingVisible()) return false;
49+
50+
switch (e.getAction()) {
51+
case MotionEvent.ACTION_MOVE:
52+
float dy = e.getY() - mTouchY;
53+
if (cp.isStatePTD()) {
54+
dy = Math.min(cp.getMaxHeadHeight() * 2, dy);
55+
dy = Math.max(0, dy);
56+
cp.getAnimProcessor().scrollHeadByMove(dy);
57+
} else if (cp.isStatePBU()) {
58+
//加载更多的动作
59+
dy = Math.min(cp.getBottomHeight() * 2, Math.abs(dy));
60+
dy = Math.max(0, dy);
61+
cp.getAnimProcessor().scrollBottomByMove(dy);
62+
}
63+
return true;
64+
case MotionEvent.ACTION_CANCEL:
65+
case MotionEvent.ACTION_UP:
66+
if (cp.isStatePTD()) {
67+
cp.getAnimProcessor().dealPullDownRelease();
68+
} else if (cp.isStatePBU()) {
69+
cp.getAnimProcessor().dealPullUpRelease();
70+
}
71+
return true;
72+
}
73+
return false;
74+
}
75+
76+
@Override
77+
public boolean onFingerScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY, float velocityY) {
78+
//手指在屏幕上滚动,如果此时正处在刷新状态,可隐藏
79+
int mTouchSlop = cp.getTouchSlop();
80+
if (cp.isRefreshVisible() && distanceY >= mTouchSlop && !cp.isOpenFloatRefresh()) {
81+
cp.setRefreshing(false);
82+
cp.getAnimProcessor().animHeadHideByVy((int) velocityY);
83+
}
84+
if (cp.isLoadingVisible() && distanceY <= -mTouchSlop) {
85+
cp.setLoadingMore(false);
86+
cp.getAnimProcessor().animBottomHideByVy((int) velocityY);
87+
}
88+
return false;
89+
}
90+
91+
@Override
92+
public boolean onFingerFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
93+
return false;
94+
}
95+
}

0 commit comments

Comments
 (0)