下拉加载,上拉刷新

现在已经找不到出处了,如果那位大神看到请与我联系。

在这里我做了一下改动,可是设置是否需要上拉或下拉:

<attr name="type" format="boolean"/>
<attr name="isUp" format="boolean"/>
app:type="false" true为允许上拉
isUp同理是否允许下拉
   <com.jz.st.shutuprojects.util.pullrefreshlayou.PullRefreshLayout
        android:id="@+id/main_prl_refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:type="false"
        android:focusableInTouchMode="true"
        android:descendantFocusability="blocksDescendants"
        android:fillViewport="true"
        >
    </com.jz.st.shutuprojects.util.pullrefreshlayou.PullRefreshLayout>

自定义类:


import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.BitmapFactory;
import android.support.annotation.Nullable;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.Transformation;
import android.widget.AbsListView;
import android.widget.ImageView;

import com.jz.st.shutuprojects.R;

/**
 * Created by SidHu on 2016/10/16.
 */
public class PullRefreshLayout extends ViewGroup {
    private static final float DECELERATE_INTERPOLATION_FACTOR = 2f;
    private static final int DRAG_MAX_DISTANCE = 64;
    private static final int INVALID_POINTER = -1;
    private static final float DRAG_RATE = .5f;

    private View mTarget;
    private ImageView mRefreshView;
    private ImageView mLoadView;
    private Interpolator mDecelerateInterpolator;
    private int mTouchSlop;
    private int mSpinnerFinalOffset;
    private int mTotalDragDistance;
    private RefreshDrawable mRefreshDrawable;
    private RefreshDrawable mLoadDrawable;
    private int mCurrentOffsetTop;
    private boolean mRefreshing;
    private boolean mLoading;
    private int mActivePointerId;
    private boolean mIsBeingDragged;
    private float mInitialMotionY;
    private int mFrom;
    private boolean mNotify;
    private OnRefreshListener mRefreshListener;
    private OnLoadListener mLoadLisener;

    public int mDurationToStartPosition;
    public int mDurationToCorrectPosition;
    private int mInitialOffsetTop;
    private boolean mDispatchTargetTouchDown;
    private float mDragPercent;

    private RefreshMode mMode = RefreshMode.getDefault();
    //之前手势的方向,为了解决同一个触点前后移动方向不同导致后一个方向会刷新的问题,
    //这里Mode.DISABLED无意义,只是一个初始值,和上拉/下拉方向进行区分
    private RefreshMode mLastDirection = RefreshMode.DISABLED;
    //当子控件移动到尽头时才开始计算初始点的位置
    private float mStartPoint;
    private boolean up;
    private boolean down;
    private boolean isDown;
    private boolean isUp;

    public PullRefreshLayout(Context context) {
        this(context, null);
    }

    public PullRefreshLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        int defaultDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);
        mDurationToStartPosition = defaultDuration;
        mDurationToCorrectPosition = defaultDuration;
        mSpinnerFinalOffset = mTotalDragDistance = dp2px(DRAG_MAX_DISTANCE);

        mRefreshView = new ImageView(context);
        setRefreshDrawable(new PlaneDrawable(getContext(), this));
        mRefreshView.setVisibility(GONE);
        addView(mRefreshView, 0);

        mLoadView = new ImageView(context);
        setLoadDrawable(new PlaneLoadDrawable(getContext(), this));
        mLoadView.setVisibility(GONE);
        addView(mLoadView, 0);

        setWillNotDraw(false);
        ViewCompat.setChildrenDrawingOrderEnabled(this, true);
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PullRefreshLayout);

        isUp = array.getBoolean(R.styleable.PullRefreshLayout_type, true);
        isDown = array.getBoolean(R.styleable.PullRefreshLayout_isUp, true);
    }


    public void setRefreshDrawable(RefreshDrawable drawable) {
        setRefreshing(false);
        mRefreshDrawable = drawable;
        mRefreshView.setImageDrawable(mRefreshDrawable);
    }

    public void setLoadDrawable(RefreshDrawable drawable) {
        setLoading(false);
        mLoadDrawable = drawable;
        mLoadView.setImageDrawable(mLoadDrawable);
    }

    public int getFinalOffset() {
        return mSpinnerFinalOffset;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        ensureTarget();
        if (mTarget == null)
            return;

        widthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth() - getPaddingRight() - getPaddingLeft(), MeasureSpec.EXACTLY);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY);
        mTarget.measure(widthMeasureSpec, heightMeasureSpec);
        mRefreshView.measure(widthMeasureSpec, heightMeasureSpec);
        mLoadView.measure(widthMeasureSpec, heightMeasureSpec);
    }

    private void ensureTarget() {
        if (mTarget != null)
            return;
        if (getChildCount() > 0) {
            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                if (child != mRefreshView && child != mLoadView)
                    mTarget = child;
            }
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (!isEnabled() || (canChildScrollUp() && canChildScrollDown() && !mRefreshing)) {
            return false;
        }

        final int action = MotionEventCompat.getActionMasked(ev);

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                if (!mRefreshing || !mLoading) {
                    setTargetOffsetTop(0, true);
                }
                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
                mIsBeingDragged = false;
                final float initialMotionY = getMotionEventY(ev, mActivePointerId);
                if (initialMotionY == -1) {
                    return false;
                }
                mInitialMotionY = initialMotionY;
                mInitialOffsetTop = mCurrentOffsetTop;
                mDispatchTargetTouchDown = false;
                mDragPercent = 0;
                mStartPoint = mInitialMotionY;

                //这里用up/down记录子控件能否下拉,如果当前子控件不能上下滑动,但当手指按下并移动子控件时,控件就会变得可滑动
                //后面的一些处理不能直接使用canChildScrollUp/canChildScrollDown
                //但仍存在问题:当数据不满一屏且设置可以上拉模式后,多次快速上拉会激发上拉加载
                up = canChildScrollUp();
                down = canChildScrollDown();
                break;
            case MotionEvent.ACTION_MOVE:
                if (mActivePointerId == INVALID_POINTER) {
                    return false;
                }
                final float y = getMotionEventY(ev, mActivePointerId);
                if (y == -1) {
                    return false;
                }

                final float yDiff = y - mStartPoint;

                if ((mLastDirection == RefreshMode.PULL_FROM_START && yDiff < 0) ||
                        (mLastDirection == RefreshMode.PULL_FROM_END && yDiff > 0)) {
                    return false;
                }
                //下拉或上拉时,子控件本身能够滑动时,记录当前手指位置,当其滑动到尽头时,
                //mStartPoint作为下拉刷新或上拉加载的手势起点
                if ((canChildScrollUp() && yDiff > 0) || (canChildScrollDown() && yDiff < 0)) {
                    mStartPoint = y;
                }
                //下拉
                if (yDiff > mTouchSlop) {
                    //若当前子控件能向下滑动,或者上个手势为上拉,则返回
                    if (canChildScrollUp() || mMode == RefreshMode.PULL_FROM_END) {
                        mIsBeingDragged = false;
                        return false;
                    }
                    if ((mMode == RefreshMode.PULL_FROM_START) || (mMode == RefreshMode.BOTH)) {
                        mIsBeingDragged = true;
                        mLastDirection = RefreshMode.PULL_FROM_START;
                    }
                }
                //上拉
                else if (-yDiff > mTouchSlop) {
                    //若当前子控件能向上滑动,或者上个手势为下拉,则返回
                    if (canChildScrollDown() || mMode == RefreshMode.PULL_FROM_START) {
                        mIsBeingDragged = false;
                        return false;
                    }
                    //若子控件不能上下滑动,说明数据不足一屏,若不满屏不加载,返回
                    if (!up && !down) {
                        mIsBeingDragged = false;
                        return false;
                    }
                    if ((mMode == RefreshMode.PULL_FROM_END) || (mMode == RefreshMode.BOTH)) {
                        mIsBeingDragged = true;
                        mLastDirection = RefreshMode.PULL_FROM_END;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mIsBeingDragged = false;
                mActivePointerId = INVALID_POINTER;
                mLastDirection = RefreshMode.DISABLED;
                break;
            case MotionEventCompat.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;
        }

        return mIsBeingDragged;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        if (!mIsBeingDragged) {
            return super.onTouchEvent(ev);
        }

        final int action = MotionEventCompat.getActionMasked(ev);

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mInitialMotionY = ev.getY();
                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
                mIsBeingDragged = false;
                mDragPercent = 0;
                mStartPoint = mInitialMotionY;

                up = canChildScrollUp();
                down = canChildScrollDown();
                break;
            case MotionEvent.ACTION_MOVE: {
                final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
                if (pointerIndex < 0) {
                    return false;
                }

                final float y = MotionEventCompat.getY(ev, pointerIndex);
                final float yDiff = y - mStartPoint;

                if ((mLastDirection == RefreshMode.PULL_FROM_START && yDiff < 0)
                        || (mLastDirection == RefreshMode.PULL_FROM_END && yDiff > 0)) {
                    return true;
                }

                if (!mIsBeingDragged && (yDiff > 0 && mLastDirection == RefreshMode.PULL_FROM_START)
                        || (yDiff < 0 && mLastDirection == RefreshMode.PULL_FROM_END)) {
                    mIsBeingDragged = true;
                }

                int targetY;
                if (mRefreshing || mLoading) {
                    targetY = (int) (mInitialOffsetTop + yDiff);
                    if ((mRefreshing && canChildScrollUp()) || (mLoading && canChildScrollDown())) {
                        targetY = -1;
                        mInitialMotionY = y;
                        mInitialOffsetTop = 0;
                        if (mDispatchTargetTouchDown) {
                            mTarget.dispatchTouchEvent(ev);
                        } else {
                            MotionEvent obtain = MotionEvent.obtain(ev);
                            obtain.setAction(MotionEvent.ACTION_DOWN);
                            mDispatchTargetTouchDown = true;
                            mTarget.dispatchTouchEvent(obtain);
                        }
                    } else {
                        if (targetY < 0) {
                            if (mDispatchTargetTouchDown) {
                                mTarget.dispatchTouchEvent(ev);
                            } else {
                                MotionEvent obtain = MotionEvent.obtain(ev);
                                obtain.setAction(MotionEvent.ACTION_DOWN);
                                mDispatchTargetTouchDown = true;
                                mTarget.dispatchTouchEvent(obtain);
                            }
                            targetY = 0;
                        } else if (targetY > mTotalDragDistance) {
                            targetY = mTotalDragDistance;
                        } else {
                            if (mDispatchTargetTouchDown) {
                                MotionEvent obtain = MotionEvent.obtain(ev);
                                obtain.setAction(MotionEvent.ACTION_CANCEL);
                                mDispatchTargetTouchDown = false;
                                mTarget.dispatchTouchEvent(obtain);
                            }
                        }
                    }
                    setTargetOffsetTop(targetY - mCurrentOffsetTop, true);
                } else {
                    final float scrollTop = yDiff * DRAG_RATE;
                    float originalDragPercent = scrollTop / mTotalDragDistance;
                    mDragPercent = Math.min(1f, Math.abs(originalDragPercent));//拖动的百分比
                    float extraOS = Math.abs(scrollTop) - mTotalDragDistance;//弹簧效果的位移
                    float slingshotDist = mSpinnerFinalOffset;
                    //当弹簧效果位移小余0时,tensionSlingshotPercent为0,否则取弹簧位移于总高度的比值,最大为2
                    float tensionSlingshotPercent = Math.max(0, Math.min(extraOS, slingshotDist * 2) / slingshotDist);
                    //对称轴为tensionSlingshotPercent = 2的二次函数,0到2递增
                    float tensionPercent = (float) ((tensionSlingshotPercent / 4) - Math.pow((tensionSlingshotPercent / 4), 2)) * 2f;
                    float extraMove = (slingshotDist) * tensionPercent * 2;
                    targetY = (int) ((slingshotDist * mDragPercent) + extraMove);
                    if (originalDragPercent < 0) {
                        if (isUp) {
                            //上拉加载
                            if (mLoadView.getVisibility() != VISIBLE) {
                                mLoadView.setVisibility(VISIBLE);
                            }
                            if (Math.abs(scrollTop) < mTotalDragDistance) {
                                mLoadDrawable.setPercent(mDragPercent);
                            }
                            setTargetOffsetTop(-targetY - mCurrentOffsetTop, true);
                        }


                    } else {
                        if (isDown){
                            //下拉刷新
                            targetY = (int) ((slingshotDist * mDragPercent) + extraMove);
                            if (mRefreshView.getVisibility() != View.VISIBLE) {
                                mRefreshView.setVisibility(View.VISIBLE);
                            }
                            if (scrollTop < mTotalDragDistance) {
                                mRefreshDrawable.setPercent(mDragPercent);
                            }
                            setTargetOffsetTop(targetY - mCurrentOffsetTop, true);
                        }

                    }
                }
                break;
            }
            case MotionEventCompat.ACTION_POINTER_DOWN:
                final int index = MotionEventCompat.getActionIndex(ev);
                mActivePointerId = MotionEventCompat.getPointerId(ev, index);
                break;
            case MotionEventCompat.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL: {
                if (mActivePointerId == INVALID_POINTER) {
                    return false;
                }
                if (mRefreshing || mLoading) {
                    if (mDispatchTargetTouchDown) {
                        mTarget.dispatchTouchEvent(ev);
                        mDispatchTargetTouchDown = false;
                    }
                    return false;
                }
                final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
                final float y = MotionEventCompat.getY(ev, pointerIndex);
                final float overscrollTop = (y - mInitialMotionY) * DRAG_RATE;
                mIsBeingDragged = false;
                if (overscrollTop > mTotalDragDistance && mCurrentOffsetTop > mTotalDragDistance) {
                    setRefreshing(true, true);
                    mLastDirection = RefreshMode.PULL_FROM_START;
                } else if (Math.abs(overscrollTop) > mTotalDragDistance && mCurrentOffsetTop < -mTotalDragDistance) {
                    setLoading(true);
                    mLastDirection = RefreshMode.PULL_FROM_END;
                } else {
                    mRefreshing = false;
                    animateOffsetToStartPosition();
                }
                mActivePointerId = INVALID_POINTER;
                mLastDirection = RefreshMode.DISABLED;
                return false;
            }
        }

        return true;
    }

    public void setDurations(int durationToStartPosition, int durationToCorrectPosition) {
        mDurationToStartPosition = durationToStartPosition;
        mDurationToCorrectPosition = durationToCorrectPosition;
    }

    private void animateOffsetToStartPosition() {
        mFrom = mCurrentOffsetTop;
        mAnimateToStartPosition.reset();
        mAnimateToStartPosition.setDuration(mDurationToStartPosition);
        mAnimateToStartPosition.setInterpolator(mDecelerateInterpolator);
        mAnimateToStartPosition.setAnimationListener(mToStartListener);
        mRefreshView.clearAnimation();
        mRefreshView.startAnimation(mAnimateToStartPosition);
    }

    private void animateOffsetToCorrectPosition() {
        mFrom = mCurrentOffsetTop;
        mAnimateToCorrectPosition.reset();
        mAnimateToCorrectPosition.setDuration(mDurationToCorrectPosition);
        mAnimateToCorrectPosition.setInterpolator(mDecelerateInterpolator);
        mAnimateToCorrectPosition.setAnimationListener(mRefreshAnimationListener);
        mRefreshView.clearAnimation();
        mRefreshView.startAnimation(mAnimateToCorrectPosition);
    }

    private void animateLoadOffsetToCorrectPosition() {
        mFrom = mCurrentOffsetTop;
        mAnimateLoadToCorrectPosition.reset();
        mAnimateLoadToCorrectPosition.setDuration(mDurationToCorrectPosition);
        mAnimateLoadToCorrectPosition.setInterpolator(mDecelerateInterpolator);
        mAnimateLoadToCorrectPosition.setAnimationListener(mRefreshLoadAnimationListener);
        mLoadView.clearAnimation();
        mLoadView.startAnimation(mAnimateLoadToCorrectPosition);
    }

    private final Animation mAnimateToCorrectPosition = new Animation() {
        @Override
        public void applyTransformation(float interpolatedTime, Transformation t) {
            int endTarget = mSpinnerFinalOffset;
            int targetTop = (mFrom + (int) ((endTarget - mFrom) * interpolatedTime));
            int offset = targetTop - mTarget.getTop();
            setTargetOffsetTop(offset, false /* requires update */);
        }
    };

    private final Animation mAnimateLoadToCorrectPosition = new Animation() {
        @Override
        public void applyTransformation(float interpolatedTime, Transformation t) {
            int endTarget = -mSpinnerFinalOffset;
            int targetTop = (mFrom + (int) ((endTarget - mFrom) * interpolatedTime));
            int offset = targetTop - mTarget.getTop();
            setTargetOffsetTop(offset, false /* requires update */);
        }
    };

    private final Animation mAnimateToStartPosition = new Animation() {
        @Override
        public void applyTransformation(float interpolatedTime, Transformation t) {
            moveToStart(interpolatedTime);
        }
    };

    private void moveToStart(float interpolatedTime) {
        int targetTop = mFrom - (int) (mFrom * interpolatedTime);
        int offset = targetTop - mTarget.getTop();
        setTargetOffsetTop(offset, false);
        if (offset > 0) {
            mRefreshDrawable.setPercent(mDragPercent * (1 - interpolatedTime));
        } else {
            mLoadDrawable.setPercent(mDragPercent * (1 - interpolatedTime));
        }
    }

    public void setRefreshing(boolean refreshing) {
        if (mRefreshing != refreshing) {
            setRefreshing(refreshing, false /* notify */);
        }
    }

    private void setRefreshing(boolean refreshing, final boolean notify) {
        if (mRefreshing != refreshing) {
            mNotify = notify;
            ensureTarget();
            mRefreshing = refreshing;
            if (mRefreshing) {
                mRefreshDrawable.setPercent(1f);
                animateOffsetToCorrectPosition();
            } else {
                mLastDirection = RefreshMode.DISABLED;
                animateOffsetToStartPosition();
            }
        }
    }

    public void setLoading(boolean loading) {
        if (mLoading != loading) {
            ensureTarget();
            mLoading = loading;
            if (mLoading) {
                mLoadDrawable.setPercent(1f);
                animateLoadOffsetToCorrectPosition();
            } else {
                mLastDirection = RefreshMode.DISABLED;
                animateOffsetToStartPosition();
            }
        }
    }

    private Animation.AnimationListener mRefreshAnimationListener = new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
            mRefreshView.setVisibility(View.VISIBLE);
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            if (mRefreshing) {
                mRefreshDrawable.start();
                if (mNotify) {
                    if (mRefreshListener != null) {
                        mRefreshListener.onRefresh();
                    }
                }
            } else {
                mRefreshDrawable.stop();
                mRefreshView.setVisibility(View.GONE);
                animateOffsetToStartPosition();
            }
            mCurrentOffsetTop = mTarget.getTop();
            mLastDirection = RefreshMode.DISABLED;
        }
    };

    private Animation.AnimationListener mRefreshLoadAnimationListener = new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
            mLoadView.setVisibility(View.VISIBLE);
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            if (mLoading) {
                mLoadDrawable.start();
                if (mLoadLisener != null) {
                    mLoadLisener.onLoad();
                }
            } else {
                mLoadDrawable.stop();
                mLoadView.setVisibility(GONE);
                animateOffsetToStartPosition();
            }
            mCurrentOffsetTop = mTarget.getTop();
            mLastDirection = RefreshMode.DISABLED;
        }
    };

    private Animation.AnimationListener mToStartListener = new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
            mRefreshDrawable.stop();
            mLoadDrawable.stop();
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            mRefreshView.setVisibility(View.GONE);
            mLoadView.setVisibility(GONE);
            mCurrentOffsetTop = mTarget.getTop();
        }
    };

    private void onSecondaryPointerUp(MotionEvent ev) {
        final int pointerIndex = MotionEventCompat.getActionIndex(ev);
        final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);
        if (pointerId == mActivePointerId) {
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex);
        }
    }

    private float getMotionEventY(MotionEvent ev, int activePointerId) {
        final int index = MotionEventCompat.findPointerIndex(ev, activePointerId);
        if (index < 0) {
            return -1;
        }
        return MotionEventCompat.getY(ev, index);
    }

    private void setTargetOffsetTop(int offset, boolean requiresUpdate) {
//        mRefreshView.bringToFront();
        mTarget.offsetTopAndBottom(offset);
        mCurrentOffsetTop = mTarget.getTop();
        mRefreshDrawable.offsetTopAndBottom(offset);
        mLoadDrawable.offsetTopAndBottom(offset);
        if (requiresUpdate && android.os.Build.VERSION.SDK_INT < 11) {
            invalidate();
        }
    }

    private boolean canChildScrollUp() {
        if (android.os.Build.VERSION.SDK_INT < 14) {
            if (mTarget instanceof AbsListView) {
                final AbsListView absListView = (AbsListView) mTarget;
                return absListView.getChildCount() > 0
                        && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
                        .getTop() < absListView.getPaddingTop());
            } else {
                return mTarget.getScrollY() > 0;
            }
        } else {
            return ViewCompat.canScrollVertically(mTarget, -1);
        }
    }

    public boolean canChildScrollDown() {
        if (android.os.Build.VERSION.SDK_INT < 14) {
            if (mTarget instanceof AbsListView) {
                final AbsListView absListView = (AbsListView) mTarget;
                View lastChild = absListView.getChildAt(absListView.getChildCount() - 1);
                if (lastChild != null) {
                    return (absListView.getLastVisiblePosition() == (absListView.getCount() - 1))
                            && lastChild.getBottom() > absListView.getPaddingBottom();
                } else {
                    return false;
                }
            } else {
                return mTarget.getHeight() - mTarget.getScrollY() > 0;
            }
        } else {
            return ViewCompat.canScrollVertically(mTarget, 1);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        ensureTarget();
        if (mTarget == null)
            return;

        int height = getMeasuredHeight();
        int width = getMeasuredWidth();
        int left = getPaddingLeft();
        int top = getPaddingTop();
        int right = getPaddingRight();
        int bottom = getPaddingBottom();

        mTarget.layout(left, top + mTarget.getTop(), left + width - right, top + height - bottom + mTarget.getTop());
        mRefreshView.layout(left, top, left + width - right, top + height - bottom);
        mLoadView.layout(left, top, left + width - right, top + height - bottom);
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getContext().getResources().getDisplayMetrics());
    }

    public void setOnRefreshListener(OnRefreshListener listener) {
        mRefreshListener = listener;
    }

    public void setOnLoadListener(OnLoadListener listener) {
        mLoadLisener = listener;
    }

    public interface OnLoadListener {
        void onLoad();
    }

    public interface OnRefreshListener {
        void onRefresh();
    }
}

代码:(layout是初始化)

下拉监听,在这写下拉后需要做的操作

   layout.setOnRefreshListener(new PullRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                layout.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        layout.setRefreshing(false);
                    }
                }, 1000);
            }
        });

上拉监听,在这写上拉后需要做的操作


        layout.setOnLoadListener(new PullRefreshLayout.OnLoadListener() {
            @Override
            public void onLoad() {
                layout.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        layout.setLoading(false);
                
                    }
                }, 1000);
            }
        });

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值