您的位置:首页 > 其它

[置顶] 完全自定义RecyclerView下拉刷新上拉加载

2017-08-10 17:08 633 查看
自从谷歌推出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
*/
publ
4000
ic 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, getHeaderMessageViewHeig
d399
ht(), 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐