Android自定义View(二)---拉刷新ListView 下之事件分发源码解析

来源:互联网 发布:淘宝彩票走势图 编辑:程序博客网 时间:2024/05/01 00:46

贴出来自定下拉刷新的源码,其主要部分已经贴出来了,欢迎拍砖。
git@git.oschina.net:gezihua/supro.git

package com.example.gezihua.myapplication.pull;import android.animation.ValueAnimator;import android.content.Context;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.ViewConfiguration;import android.view.animation.DecelerateInterpolator;import android.widget.RelativeLayout;import com.example.gezihua.myapplication.R;import java.lang.ref.WeakReference;/** * Created by gezihua on 16-12-20. */public class PullToRefresh extends RelativeLayout {    private boolean mIsBeingDragged;    private float mTouchSlop;    private float mStartY;    private float mLastMottionY;    private ValueAnimator mResetAnimation;    public void setmRefreshView(IPullView mRefreshView) {        this.mRefreshView = mRefreshView;    }    private IPullView mRefreshView;    public void setHeaderView(IHeaderView headerView) {        mHeaderView = headerView;    }    private IHeaderView mHeaderView;    public PullToRefresh(Context context) {        super(context);        init();    }    private void init() {        ViewConfiguration config = ViewConfiguration.get(getContext());        mTouchSlop = config.getScaledTouchSlop();        int dimensionPixelOffset = getResources().getDimensionPixelOffset(R.dimen.pull_to_refresh_max);        if (dimensionPixelOffset < MAX_PULL) {            MAX_PULL = dimensionPixelOffset;        }    }    public PullToRefresh(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public PullToRefresh(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        //能相应第一个应该是Down事件        // 对于能滚动View的View来说,这个时候应该已经滚动到最上边        if (mRefreshView == null || !mRefreshView.canScroll()) {            Log.e("suj", "can scroll" + mRefreshView.canScroll());            mIsBeingDragged = false;            return super.onInterceptTouchEvent(ev);        }        int action = ev.getAction();        Log.e("suj", "onInterceptTouchEvent" + ev.toString());        switch (action) {            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL: {                if (mIsBeingDragged) {                    return true;                }                break;            }            // 这里应该返回false ,别问我为什么            //如果子布局还要处理事件,这里一定要返回false            //真正拦截不下发的地方应该在 move 事件            case MotionEvent.ACTION_DOWN: {                return startDragging(ev);            }            case MotionEvent.ACTION_MOVE: {                return onDragging(ev);            }        }        return super.onInterceptTouchEvent(ev);    }    private boolean onDragging(MotionEvent ev) {        mLastMottionY = ev.getY();        if (mLastMottionY < mStartY) {            mIsBeingDragged = false;            return false;        }        mIsBeingDragged = true;        boolean dragging = Math.abs(mLastMottionY - mStartY) >= mTouchSlop;        //Log.e("suj","can dragging"+dragging);        return dragging;    }    private boolean startDragging(MotionEvent ev) {        mStartY = ev.getY();        mIsBeingDragged = true;        return false;    }    private boolean showHeaderView() {        if (mHeaderView == null) {            return false;        }        return mHeaderView.canRefresh();    }    private static class H extends Handler {        WeakReference<PullToRefresh> pullToRefreshRef;        public H(PullToRefresh refresh) {            pullToRefreshRef = new WeakReference<PullToRefresh>(refresh);        }        @Override        public void dispatchMessage(Message msg) {            super.dispatchMessage(msg);            if (msg.what != MSG_END_DRAGGING) {                return;            }            PullToRefresh pullToRefresh = pullToRefreshRef.get();            if (pullToRefresh == null) {                return;            }            pullToRefresh.reset();        }    }    private final static int MSG_END_DRAGGING = 1;    private H mH;    private Message generateDraggingMsg(int msg) {        Message obtain = Message.obtain();        obtain.what = msg;        return obtain;    }    private void handleEndDragging(MotionEvent ev) {        mIsBeingDragged = false;        mLastMottionY = 0;        mStartY = 0;        // 为了解决不能连续刷新的问题,应该把以前的动画以及刷新动画停止,并且重置状态        removeDelayEndDragging();        endResetAnimation();        // then we can do some refresh animator;        // if the header is not show ,we can  do animation immediately        if (showHeaderView()) {            if (mH == null) {                mH = new H(this);            }            mH.sendMessageDelayed(generateDraggingMsg(MSG_END_DRAGGING), 350);            // then we can start refresh animation            mHeaderView.showRefresh();        } else {            reset();        }    }    private void removeDelayEndDragging() {        if (mH == null) {            return;        }        mH.removeMessages(MSG_END_DRAGGING);    }    private void endResetAnimation(){        if (mResetAnimation==null){            return;        }        if (mResetAnimation.isRunning()){            mResetAnimation.cancel();        }    }    private void endHeaderAnimation(){        if (mHeaderView==null){            return;        }        mHeaderView.cancelRefresh();    }    // when destroy we must remove the delayed msg    @Override    protected void onDetachedFromWindow() {        super.onDetachedFromWindow();        removeDelayEndDragging();    }    private void reset() {        mResetAnimation = ValueAnimator.ofFloat(mRefreshView.getPullTransY(), 0);        mResetAnimation.setDuration(350);        mResetAnimation.setRepeatMode(ValueAnimator.RESTART);        mResetAnimation.setInterpolator(new DecelerateInterpolator());        mResetAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                float animatedValue = (float) animation.getAnimatedValue();                mRefreshView.setPullTransY((int) animatedValue);            }        });        mResetAnimation.start();    }    @Override    public boolean onTouchEvent(MotionEvent event) {        Log.e("suj", "onTouchEvent" + event.toString());        if (mIsBeingDragged) {            int action = event.getAction();            //Log.e("suj","onTouchEvent"+event.toString());            switch (action) {                case MotionEvent.ACTION_CANCEL:                case MotionEvent.ACTION_UP: {                    handleEndDragging(event);                    break;                }                case MotionEvent.ACTION_MOVE: {                    return handleDragging(event);                }                case MotionEvent.ACTION_DOWN: {                    break;                }            }            return true;        }        return super.onTouchEvent(event);    }    private int MAX_PULL = 300;    private boolean handleDragging(MotionEvent event) {        if (mRefreshView == null) {            return false;        }        mLastMottionY = event.getY();        if (mLastMottionY < mStartY) {            return false;        }        int lastTransY = mRefreshView.getPullTransY();        float v = mLastMottionY - mStartY;        //Log.e("suj","mLastMottionY"+mLastMottionY+"startY"+mStartY);        int pull = (lastTransY + v) / 2 > MAX_PULL ? MAX_PULL : (int) (lastTransY + v) / 2;        mRefreshView.setPullTransY(pull);        return true;    }}
0 0