public class CustomScroller extends ScrollView {
private View childView;// 子View(ScrollerView的唯一子類)
private int y;// 點選時y坐标
private Rect rect = new Rect();// 矩形(用來儲存inner的初始狀态,判斷是夠需要動畫回彈效果)
public CustomScroller(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 在xml布局繪制為界面完成時調用,
* 擷取ScrollerView中唯一的直系子布局(ScrollerView中不許包含一層ViewGroup,有且隻有一個)
*/
@Override
protected void onFinishInflate() {
if (getChildCount() > 0) {
childView = getChildAt(0);
}
super.onFinishInflate();
}
/**
* touch 事件處理
**/
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (childView != null) {
handleTouchEvent(ev);
}
return super.onTouchEvent(ev);
}
/***
* 觸摸事件
*
* @param ev
*/
public void handleTouchEvent(MotionEvent ev) {
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
y = (int) ev.getY();//按下的時候擷取到y坐标
break;
case MotionEvent.ACTION_MOVE:
int nowY = (int) ev.getY(); // 移動時的實時y坐标
int delayY = y - nowY; // 移動時的間隔
y = nowY; // 将本次移動結束時的y坐标指派給下次移動的起始坐标(也就是nowY)
if (isNeedMove()) {
if (rect.isEmpty()) {
//rect儲存childView的初始位置資訊
rect.set(childView.getLeft(), childView.getTop(), childView.getRight(), childView.getBottom());
}
//移動布局(螢幕移動的距離等于手指滑動距離的一般)
childView.layout(childView.getLeft(), childView.getTop() - delayY / 2, childView.getRight(), childView.getBottom() - delayY / 2);
}
break;
case MotionEvent.ACTION_UP:
if (isNeedAnimation()) {// 判斷rect是否為空,也就是是否被重置了
startAnim();//開始回彈動畫
}
break;
default:
break;
}
}
private void startAnim() {
TranslateAnimation anim = new TranslateAnimation(0, 0, childView.getTop(), rect.top);
anim.setDuration(200);
anim.setInterpolator(new OvershootInterpolator());//加速器
childView.startAnimation(anim);
// 将inner布局重新回到起始位置
childView.layout(rect.left, rect.top, rect.right, rect.bottom);
rect.setEmpty();
}
/**
* 判斷布局是否需要移動
* @return
*/
private boolean isNeedMove() {
int offset = childView.getMeasuredHeight() - getHeight();
int scrollY = getScrollY();
// 0是頂部,後面那個是底部(需要仔細想一下這個過程)
if (scrollY == 0 || scrollY == offset) {
return true;
}
return false;
}
public boolean isNeedAnimation() {
return !rect.isEmpty();
}
}