完全自定义RecyclerView下拉刷新上拉加载

来源:互联网 发布:游客人流量软件 编辑:程序博客网 时间:2024/05/16 12:25

自从谷歌推出SwipeRefreshLayout之后越来越多的博客都是使用SwipeRefreshLayout来完成下拉刷新,但是往往产品经理根本不会使用谷歌的样式.每个公司都有一套自己的下拉样式这个时候就需要我们完全自定义RecyclerView的下拉刷新,基本查阅了网上所有的下拉刷新,但是效果都不怎么样.个人感觉我写的这个下拉刷新效果方面绝对的66666,欢迎可以提出一些改进意见:



废话不多说 先上效果图:




RecyclerView 出现以后,Android 里的下拉刷新和加载更多实现起来就非常容易了。当然,现成的库也有很多,只是总会有不一样的需求,而且我们往往只需要最基本的下拉刷新和加载更多功能,而不需要其他多余的功能。我只需要一个最纯粹的下拉刷新和加载更多。所以,自己动手显然是最好的结果了,也算是个小练习


在介绍代码之前我们先来讲一下实现原理:


首先,我们先通过重写RecyclerView的Adapter类装饰器为起实现addHeaderView,addFootView方法来添加头部与尾部。头部的实现是通过动态的修改的头部控件的高度,尾部的实现是通过动态修改它的BottomMargin,因为尾部的是默认显示的,使用Margin好实现,如果想实现下拉刷新和上拉加载功能,那么就必须有拉伸效果,所以就像上面的那样,Header是通过设置height,Footer是通过设置BottomMargin来模拟拉伸效果。那么回弹效果呢?仅仅通过设置高度或者是间隔是达不到模拟回弹效果的,因此,就需要用Scroller来实现模拟回弹效果。


本项目我把它分为主要的五部分HeaderAndFooterWrapper,PullRefreshRecyclerView,RecyclerViewFooter,RecyclerViewHeader,MessageRelativeLayout


下面我们分开来介绍。


HeaderAndFooterWrapper


这个类主要实现了RecyclerView的addHeaderView,addFootView方法,详细资料看参考弘洋大神的Android 优雅的为RecyclerView添加HeaderView和FooterView


以下是详细代码:


/** * Created by  on 2017/7/5. * 公司:北京华星成汇文化发展有限公司 * 描述: */public class HeaderAndFooterWrapper extends RecyclerView.Adapter<RecyclerView.ViewHolder> {    private static final int BASE_ITEM_TYPE_HEADER = 100000;    private static final int BASE_ITEM_TYPE_FOOTER = 200000;    //头集合 尾结合    private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>();    private SparseArrayCompat<View> mFootViews = new SparseArrayCompat<>();    private RecyclerView.Adapter mInnerAdapter;    /**     * 把传进来的adapter赋值给成员变量     *     * @param adapter     */    public HeaderAndFooterWrapper(RecyclerView.Adapter adapter) {        mInnerAdapter = adapter;    }    private boolean isHeaderViewPos(int position) {        return position < getHeadersCount();    }    private boolean isFooterViewPos(int position) {        return position >= getHeadersCount() + getRealItemCount();    }    /**     * 添加头部方法     *     * @param view     */    public void addHeaderView(View view) {        mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER, view);    }    /**     * 添加尾部方法     *     * @param view     */    public void addFootView(View view) {        mFootViews.put(mFootViews.size() + BASE_ITEM_TYPE_FOOTER, view);    }    /**     * 获取头部集合的大小     *     * @return     */    public int getHeadersCount() {        return mHeaderViews.size();    }    /**     * 获取尾部集合的大小     *     * @return     */    public int getFootersCount() {        return mFootViews.size();    }    /**     * 获取adapter的大小     *     * @return     */    private int getRealItemCount() {        return mInnerAdapter.getItemCount();    }    @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        if (mHeaderViews.get(viewType) != null) {//            ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mHeaderViews.get(viewType));//            return holder;            return new HeaderViewHolder(mHeaderViews.get(viewType));        } else if (mFootViews.get(viewType) != null) {//            ViewHolder holder = ViewHolder.createViewHolder(parent.getContext(), mFootViews.get(viewType));//            return holder;            return new FootViewHolder(mFootViews.get(viewType));        }        return mInnerAdapter.onCreateViewHolder(parent, viewType);    }    @Override    public int getItemViewType(int position) {        if (isHeaderViewPos(position)) {            return mHeaderViews.keyAt(position);        } else if (isFooterViewPos(position)) {            return mFootViews.keyAt(position - getHeadersCount() - getRealItemCount());        }        return mInnerAdapter.getItemViewType(position - getHeadersCount());    }    @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        if (isHeaderViewPos(position)) {            return;        }        if (isFooterViewPos(position)) {            return;        }        mInnerAdapter.onBindViewHolder(holder, position - getHeadersCount());    }    @Override    public int getItemCount() {        return getHeadersCount() + getFootersCount() + getRealItemCount();    }    @Override    public void onAttachedToRecyclerView(RecyclerView recyclerView) {        mInnerAdapter.onAttachedToRecyclerView(recyclerView);        /**         * 解决网格布局问题         */        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();        if (layoutManager instanceof GridLayoutManager) {            final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {                @Override                public int getSpanSize(int position) {                    int viewType = getItemViewType(position);                    if (mHeaderViews.get(viewType) != null) {                        return gridLayoutManager.getSpanCount();                    } else if (mFootViews.get(viewType) != null) {                        return gridLayoutManager.getSpanCount();                    } else {                        return 1;                    }                }            });        }    }//    /**//     * 解决 StaggeredGridLayoutManager样式的加头部问题,暂时没用//     * @param holder//     *///    @Override//    public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {//        mInnerAdapter.onViewAttachedToWindow(holder);//        int position = holder.getLayoutPosition();//        if (isHeaderViewPos(position) || isFooterViewPos(position)) {//            ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();////            if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams) {////                StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;////                p.setFullSpan(true);//            }//        }//    }    private class HeaderViewHolder extends RecyclerView.ViewHolder {        HeaderViewHolder(View itemView) {            super(itemView);        }    }    private class FootViewHolder extends RecyclerView.ViewHolder {        FootViewHolder(View itemView) {            super(itemView);        }    }}


RecyclerViewHeader


RecyclerViewHeader继承自LinearLayout用来实现下拉刷新时的界面展示,可以分为三种状态:正常、准备刷新、正在加载。在添加布局文件的时候,指定高度为0,这是为了隐藏header,setState()是设置header的状态,因为header需要根据不同的状态,完成控件隐藏、显示、改变文字等操作,这个方法主要是在PullRefreshRecyclerView里面调用。除此之外,还有setVisiableHeight()和getVisiableHeight(),这两个方法是为了设置和获取Header中根布局文件的高度属性,从而完成拉伸和收缩的效果


/** * Created by 刘龙 on 2017/7/18. * 公司:北京华星成汇文化发展有限公司 * 描述: */public class RecyclerViewHeader extends LinearLayout {    /**     * 动画执行时间     */    private final int ROTATE_ANIM_DURATION = 180;    public final static int STATE_NORMAL = 0;    public final static int STATE_READY = 1;    public final static int STATE_REFRESHING = 2;    /**     * 当前状态     */    private int mState = STATE_NORMAL;    //获取到头布局    private LinearLayout mContainer;    //获取到控件    private ImageView mArrowImageView;    //    private ProgressBar mProgressBar;    private TextView mHintTextView;    //初始化动画//    private RotateAnimation mRotateUpAnim;//    private Animation mRotateDownAnim;    private TextView mTitleTextView;    private RelativeLayout mRealityContent;    public RecyclerViewHeader(Context context) {        this(context, null);    }    public RecyclerViewHeader(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public RecyclerViewHeader(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }    private void init(Context context) {        // 初始情况,设置下拉刷新view高度为0        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0);        //获取下拉布局        mContainer = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.pullrefrefh_recyclerview_header, (ViewGroup) getParent(), true);        //添加到改容器        addView(mContainer, lp);        //显示位置下面        setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL);        //初始化控件        mRealityContent = (RelativeLayout) mContainer.findViewById(R.id.pullRefresh_reality_content);        mArrowImageView = (ImageView) mContainer.findViewById(R.id.pullRefresh_arrow);        mHintTextView = (TextView) mContainer.findViewById(R.id.pullRefresh_text);//        mProgressBar = (ProgressBar) findViewById(R.id.pullRefresh_progressbar);        mTitleTextView = (TextView) mContainer.findViewById(R.id.pullRefresh_title);        //初始化动画//        mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,//                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,//                0.5f);//        mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);//        mRotateUpAnim.setFillAfter(true);//        mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,//                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,//                0.5f);//        mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);//        mRotateDownAnim.setFillAfter(true);    }    public void setState(int state) {        //如果状态相同  直接返回        if (mState == state) return;        //如果传进来的是刷新状态        if (state == STATE_REFRESHING) {    // 正在加载显示圆圈进度//            mArrowImageView.clearAnimation();//            mArrowImageView.setVisibility(View.INVISIBLE);//            mProgressBar.setVisibility(View.VISIBLE);        } else {    // 显示箭头图片//            mArrowImageView.setVisibility(View.VISIBLE);//            mProgressBar.setVisibility(View.INVISIBLE);        }        switch (state) {            case STATE_NORMAL://正常状态                if (mState == STATE_READY) {//                    mArrowImageView.startAnimation(mRotateDownAnim);                }                if (mState == STATE_REFRESHING) {//                    mArrowImageView.clearAnimation();                }                mHintTextView.setText("下拉刷新");                break;            case STATE_READY://可以刷新状态                if (mState != STATE_READY) {//                    mArrowImageView.clearAnimation();//                    mArrowImageView.startAnimation(mRotateUpAnim);                    mHintTextView.setText("松开刷新数据");                }                break;            case STATE_REFRESHING://刷新状态                mHintTextView.setText("正在加载...");                break;            default:        }        mState = state;    }    /**     * 设置显示的图片     *     * @param imagePath     */    public void setPullImage(String imagePath) {        Drawable fromPath = Drawable.createFromPath(imagePath);        Bitmap bitmap = BitmapFactory.decodeFile(imagePath);//        mArrowImageView.setBackground(fromPath);        mArrowImageView.setImageBitmap(bitmap);    }    /**     * 设置显示的文字     *     * @param text     */    public void setPullContent(String text) {        mTitleTextView.setText(text);    }    /**     * 获取本身实际的高度     */    public int getRealityHeight() {        return mRealityContent.getHeight();    }    /**     * 设置隐藏高度     *     * @param height     */    public void setVisibleHeight(int height) {        if (height < 0) {            height = 0;        }        LayoutParams lp = (LayoutParams) mContainer.getLayoutParams();        lp.height = height;        mContainer.setLayoutParams(lp);    }    /**     * 获取隐藏的高度     *     * @return     */    public int getVisibleHeight() {        return mContainer.getLayoutParams().height;    }}



说完了Header,我们再看看Footer。Footer是为了完成加载更多功能时候的界面展示,基本思路和Header是一样的,不过Footer的拉伸和显示效果不是通过高度来模拟的,而是通过设置BottomMargin来完成的。



/** * Created by 刘龙 on 2017/8/9. * 公司:北京华星成汇文化发展有限公司 * 描述: */public class RecyclerViewFooter extends LinearLayout {    public final static int STATE_NORMAL = 0;    public final static int STATE_READY = 1;    public final static int STATE_LOADING = 2;    private Context context;    private View contentView;    private View progressBar;    private TextView hintView;    public RecyclerViewFooter(Context context) {        this(context, null);    }    public RecyclerViewFooter(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public RecyclerViewFooter(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        this.context = context;        initView();    }    private void initView() {        LinearLayout moreView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.pullrefrefh_recyclerview_footer, null);        addView(moreView);        moreView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));        contentView = moreView.findViewById(R.id.pullrefrefh_footer_content);        progressBar = moreView.findViewById(R.id.pullrefrefh_footer_ProgressBar);        hintView = (TextView) moreView.findViewById(R.id.pullrefrefh_footer_hint_TextView);    }    /**     * 设置状态     *     * @param state     */    public void setState(int state) {        hintView.setVisibility(View.INVISIBLE);        progressBar.setVisibility(View.INVISIBLE);        hintView.setVisibility(View.INVISIBLE);        if (state == STATE_READY) {            hintView.setVisibility(View.VISIBLE);            hintView.setText("松开载入更多");        } else if (state == STATE_LOADING) {            progressBar.setVisibility(View.VISIBLE);        } else {            hintView.setVisibility(View.VISIBLE);            hintView.setText("查看更多");        }    }    /**     * 设置距离下边的BottomMargin     *     * @param height     */    public void setBottomMargin(int height) {        if (height < 0) return;        LayoutParams lp = (LayoutParams) contentView.getLayoutParams();        lp.bottomMargin = height;        contentView.setLayoutParams(lp);    }    /**     * 获取BottomMargin     *     * @return     */    public int getBottomMargin() {        LayoutParams lp = (LayoutParams) contentView.getLayoutParams();        return lp.bottomMargin;    }    /**     * hide footer when disable pull load more     */    public void hide() {        LayoutParams lp = (LayoutParams) contentView.getLayoutParams();        lp.height = 0;        contentView.setLayoutParams(lp);    }    /**     * show footer     */    public void show() {        LayoutParams lp = (LayoutParams) contentView.getLayoutParams();        lp.height = LayoutParams.WRAP_CONTENT;        contentView.setLayoutParams(lp);    }}


MessageRelativeLayout


该类主要是为了实现在刷新完毕的时候可以显示一个更新了多少条,网络错误等等的提示语:在添加布局文件的时候,指定高度为0,这是为了隐藏提示语,实现思路与头布局类似,如不需要此功能可忽略,不会影响代码的使用


/** * Created by  on 2017/7/18. * 公司:北京华星成汇文化发展有限公司 * 描述: */public class MessageRelativeLayout extends RelativeLayout {    //显示消息的控件    private LinearLayout mHeaderMessageView;    private TextView mHeaderMessageText;    private int mHeaderMessageViewHeight;    //滚动类    private Scroller mScroller;    public MessageRelativeLayout(Context context) {        this(context, null);    }    public MessageRelativeLayout(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public MessageRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context);    }    private void init(Context context) {        //滚动类        mScroller = new Scroller(context, new DecelerateInterpolator());        //初始化一个显示消息的textView        mHeaderMessageView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.pullrefresh_header_message, (ViewGroup) getParent(), false);        mHeaderMessageView.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 0));        mHeaderMessageText = (TextView) mHeaderMessageView.findViewById(R.id.pullRefresh_message);        // 初始化 头部高度        mHeaderMessageText.getViewTreeObserver().addOnGlobalLayoutListener(                new ViewTreeObserver.OnGlobalLayoutListener() {                    @Override                    public void onGlobalLayout() {                        mHeaderMessageViewHeight = mHeaderMessageText.getHeight();//57                        getViewTreeObserver().removeOnGlobalLayoutListener(this);                    }                });    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        //确保添加到后面        addView(mHeaderMessageView, 1);    }    public void showMessage() {        mScroller.startScroll(0, getHeaderMessageViewHeight(), 0, 0, PullRefreshRecyclerView.SCROLL_DURATION);        invalidate();    }    public void hideMessage() {        mScroller.startScroll(0, getVisibleHeight(), 0, -getVisibleHeight(), PullRefreshRecyclerView.SCROLL_DURATION);        invalidate();    }    /**     * 设置消息     */    public void setMessage(String message) {        mHeaderMessageText.setText(message);    }    /**     * 获取消息总高度     *     * @return     */    public int getHeaderMessageViewHeight() {        return mHeaderMessageViewHeight;    }    /**     * 设置隐藏高度     *     * @param height     */    private void setVisibleHeight(int height) {        if (height < 0) {            height = 0;        }       LayoutParams lp = (LayoutParams) mHeaderMessageView.getLayoutParams();        lp.height = height;        mHeaderMessageView.setLayoutParams(lp);    }    /**     * 获取隐藏的高度     *     * @return     */    public int getVisibleHeight() {        return mHeaderMessageView.getLayoutParams().height;    }    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) {                setVisibleHeight(mScroller.getCurrY());            postInvalidate();        }        super.computeScroll();    }}


PullRefreshRecyclerView


在了解了Header,Footer和Message之后,我们就要介绍最核心的PullRefreshRecyclerView的代码实现了。便于观看,本代码有部分删减重构


/** * Created by 刘龙 on 2017/7/18. * 公司:北京华星成汇文化发展有限公司 * 描述: */public class PullRefreshRecyclerView extends RecyclerView {    private float mLastY = -1; // save event y    /**     * 滚动需要的时间     */    public final static int SCROLL_DURATION = 200;    /**     * 提示消息显示时间     */    public final static int MESSAGE_SHOW_DURATION = 2000;    /**     * 阻尼效果     */    private final static float OFFSET_RADIO = 1.5f;    /**     * 上拉加载的距离,默认50px     */    private static final int PULL_LOAD_MORE_DELTA = 50;    /**     * 是否设置为自动加载更多,目前没实现     */    private boolean mEnableAutoLoading = false;    /**     * 是否可以上拉  默认可以     */    private boolean mEnablePullLoad = true;    /**     * 是否可以下拉   默认可以     */    private boolean mEnablePullRefresh = true;    /**     * 是否正在加载     */    private boolean mPullLoading = false;    /**     * 是否正在刷新     */    private boolean mPullRefreshing = false;    /**     * 区分上拉和下拉     */    private int mScrollBack;    private final static int SCROLLBACK_HEADER = 0;    private final static int SCROLLBACK_FOOTER = 1;    //滚动类    private Scroller mScroller;    //头布局控件    private RecyclerViewHeader mHeaderView;    //尾控件    private RecyclerViewFooter mFooterView;    //消息提示类    private MessageRelativeLayout mParent;    //adapter的装饰类    private HeaderAndFooterWrapper mHeaderAndFooterWrapper;    public PullRefreshRecyclerView(Context context) {        this(context, null);    }    public PullRefreshRecyclerView(Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public PullRefreshRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init(context);    }    private void init(Context context) {        //滚动类        mScroller = new Scroller(context, new DecelerateInterpolator());        //获取到头布局        mHeaderView = new RecyclerViewHeader(context);        mHeaderView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));        //获取尾布局        mFooterView = new RecyclerViewFooter(context);        mFooterView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));    }    private Adapter adapter;    @Override    public void setAdapter(Adapter adapter) {        this.adapter = adapter;        mHeaderAndFooterWrapper = new HeaderAndFooterWrapper(adapter);        super.setAdapter(mHeaderAndFooterWrapper);        //添加头,确保是第一个        mHeaderAndFooterWrapper.addHeaderView(mHeaderView);        //添加尾,确保是第最后一个        mHeaderAndFooterWrapper.addFootView(mFooterView);        //获取到它的父容器        if (getParent() instanceof MessageRelativeLayout) {            mParent = (MessageRelativeLayout) getParent();        }    }    @Override    public boolean onTouchEvent(MotionEvent e) {        if (mLastY == -1) {            mLastY = e.getRawY();        }        switch (e.getAction()) {            case MotionEvent.ACTION_DOWN:                //按下的时候记录值                mLastY = e.getRawY();                break;            case MotionEvent.ACTION_MOVE:                float moveY = e.getRawY();                //手指滑动的差值                float distanceY = moveY - mLastY;                mLastY = moveY;                //第一个条目完全显示   //头部高度大于0   deltaY大于0  向下移动                if ((((LinearLayoutManager) getLayoutManager()).findFirstCompletelyVisibleItemPosition() == 0 || ((LinearLayoutManager) getLayoutManager()).findFirstCompletelyVisibleItemPosition() == 1) && (mHeaderView.getVisibleHeight() > 0 || distanceY > 0)) {                    // 更新头部高度                    updateHeaderHeight(distanceY / OFFSET_RADIO);                } else if (isSlideToBottom() && (mFooterView.getBottomMargin() > 0 || distanceY < 0)) {                    Log.e("PullRefreshRecyclerView","-------111------"+distanceY);                    //已经到达底部,改变状态或者自动加载                    updateFooterHeight(-distanceY / OFFSET_RADIO);                }else if (distanceY > 0){                    updateFooterHeight(-distanceY / OFFSET_RADIO);                }                break;            default:                mLastY = -1; // 复位                if ((((LinearLayoutManager) getLayoutManager()).findFirstCompletelyVisibleItemPosition() == 0 || ((LinearLayoutManager) getLayoutManager()).findFirstCompletelyVisibleItemPosition() == 1)) {                    // 松手的时候  高度大于  一定值  调用刷新                    if (mEnablePullRefresh && mHeaderView.getVisibleHeight() > mHeaderView.getRealityHeight()) {                        //变为刷新状态                        mPullRefreshing = true;                        mHeaderView.setState(RecyclerViewHeader.STATE_REFRESHING);                        //回调事件                        if (mOnRefreshListener != null) {                            mOnRefreshListener.onRefresh();                        }                    }                    resetHeaderHeight();                } else if (isSlideToBottom()) {                    // invoke load more.                    if (mEnablePullLoad && mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA && !mPullLoading) {                        mPullLoading = true;                        mFooterView.setState(RecyclerViewFooter.STATE_LOADING);                        if (mOnRefreshListener != null) {                            mOnRefreshListener.onLoadMore();                        }                    }                    resetFooterHeight();                } else {//                    resetFooterHeight();                    resetHeaderHeight();                }                break;        }        return super.onTouchEvent(e);    }    /**     * 更新尾部加载     *     * @param distance     */    private void updateFooterHeight(float distance) {        int height = mFooterView.getBottomMargin() + (int) distance;        Log.e("PullRefreshRecyclerView","-------------"+height);        if (mEnablePullLoad && !mPullLoading) {            if (height > PULL_LOAD_MORE_DELTA) {                //改变状态                mFooterView.setState(RecyclerViewFooter.STATE_READY);            } else {                mFooterView.setState(RecyclerViewFooter.STATE_NORMAL);            }        }        mFooterView.setBottomMargin(height);    }    /**     * 更新头部刷新     *     * @param distance     */    private void updateHeaderHeight(float distance) {        // 设置头部高度,原先的高度加上        mHeaderView.setVisibleHeight((int) distance + mHeaderView.getVisibleHeight());        // 未处于刷新状态,更新箭头        if (mEnablePullRefresh && !mPullRefreshing) {            //下拉高度到达可以刷新的位置            if (mHeaderView.getVisibleHeight() > mHeaderView.getRealityHeight()) {                mHeaderView.setState(RecyclerViewHeader.STATE_READY);            } else {                mHeaderView.setState(RecyclerViewHeader.STATE_NORMAL);            }        }        //移动到顶部        smoothScrollBy(0, 0);    }    /**     * 重置头部高度     */    private void resetHeaderHeight() {        int height = mHeaderView.getVisibleHeight();        if (height == 0) // 如果=0  是不可见的 直接返回            return;        if (mPullRefreshing && height <= mHeaderView.getRealityHeight()) {            return;        }        int finalHeight = 0;        if (mPullRefreshing && height > mHeaderView.getRealityHeight()) {            finalHeight = mHeaderView.getRealityHeight();        }        if (mParent != null) {            if (mHeaderView.getVisibleHeight() == mParent.getHeaderMessageViewHeight()) {                finalHeight = mParent.getHeaderMessageViewHeight();            }        }        mScrollBack = SCROLLBACK_HEADER;//设置标识        mScroller.startScroll(0, height, 0, finalHeight - height, SCROLL_DURATION);        // 触发计算滚动        invalidate();    }    /**     * 重置尾部高度     */    private void resetFooterHeight() {        int bottomMargin = mFooterView.getBottomMargin();        if (bottomMargin > 0) {            mScrollBack = SCROLLBACK_FOOTER;//设置标识            mScroller.startScroll(0, bottomMargin, 0, -bottomMargin, SCROLL_DURATION);            invalidate();        }    }    /**     * 停止刷新     */    public void stopRefresh() {        mScrollBack = SCROLLBACK_HEADER;//设置标识        int obligateHeight;        if (mParent != null) {            obligateHeight = mParent.getHeaderMessageViewHeight();        } else {            obligateHeight = 0;        }        int height = mHeaderView.getVisibleHeight();        if (mPullRefreshing) {            //是否复位            mPullRefreshing = false;            //显示更新了多少条消息            if (mParent != null) {                mParent.showMessage();            }            mScroller.startScroll(0, height, 0, obligateHeight - height, SCROLL_DURATION);            // 触发计算滚动            invalidate();            //延时执行复位移动            if (mParent != null) {                handler.removeCallbacksAndMessages(null);                handler.sendEmptyMessageDelayed(1, MESSAGE_SHOW_DURATION);            }        }    }    /**     * 停止加载     */    public void stopLoadMore() {        if (mPullLoading) {            mPullLoading = false;            mFooterView.setState(RecyclerViewFooter.STATE_NORMAL);        }    }    /**     * 消息     */    private Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            if (mHeaderView.getVisibleHeight() == mParent.getHeaderMessageViewHeight()) {//                resetHeaderHeight();                mScroller.startScroll(0, mHeaderView.getVisibleHeight(), 0, -mHeaderView.getVisibleHeight(), SCROLL_DURATION);                postInvalidate();            }            mParent.hideMessage();        }    };    @Override    public void computeScroll() {        if (mScroller.computeScrollOffset()) {            if (mScrollBack == SCROLLBACK_HEADER) {                mHeaderView.setVisibleHeight(mScroller.getCurrY());            } else {                mFooterView.setBottomMargin(mScroller.getCurrY());            }            postInvalidate();        }        super.computeScroll();    }    private OnRefreshListener mOnRefreshListener;    public void setOnRefreshListener(OnRefreshListener onRefreshListener) {        mOnRefreshListener = onRefreshListener;    }    /**     * 刷新接口,     */    public interface OnRefreshListener {        void onRefresh();        void onLoadMore();    }    /**     * 判断是否到底     *     * @return     */    private boolean isSlideToBottom() {        return computeVerticalScrollExtent() + computeVerticalScrollOffset() >= computeVerticalScrollRange();    }}



最后重要的事说三遍:本项目扩展性极高,建议下载源码观看可更清晰的了解此项目的结构


源码地址:http://download.csdn.net/download/q714093365/9928217


转载请注明出处:http://blog.csdn.net/q714093365/article/details/77063084





原创粉丝点击