天天看點

android 阻尼效果

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();
    }
}