上篇中讲到的RecycleView实现的是ListView的刷新效果,还有部分问题,这里我将在下面一一道来,本次又添加了GridView的刷新效果如下图:
这里我要说一下GridLayoutManager,GridLayoutManager是集成LinerLayoutManager的,所以上篇中的获取最后一个position的逻辑不用更改。
public void setLayoutManger(final LayoutManager layout, final int spanCount) {
if (layout instanceof GridLayoutManager) {
final GridLayoutManager m = (GridLayoutManager) layout;
m.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (mState == STATE_FRESHING) {
if (position == 0 && mRefreshPosition == HEAD) {
return spanCount;
} else if (mRefreshPosition == BOTTOM && position == getAdapter().getItemCount() - 1) {
return spanCount;
}
}
return 1;
}
});
setLayoutManager(layout);
}
}
这个方法,提供了刷新item的占有比例的解决办法,外部将LayoutManager传递进来,若果用户选择的是GridView的效果,我们就为头部和尾部设置上权重,注意:这里的spanCount是指占用一行的item的个位数,总个数由用户创建的GrideLayoutManager的第二个参数决定,这样,当状态为刷新状态时,我们让其消费掉一行,也就是占有m份。
这篇解决了头尾刷新时出现的问题:新增了一个字段mRefreshPosition
初始值为-1,0,代表头部刷新,1,代表尾部刷新,接下来,我们要修改两个个方法
public int getHeadCount() {
return mRefreshPosition==HEAD ? 1 : 0;
}
public int getFootCount() {
return mRefreshPosition==BOTTOM ? 1 : 0;
上篇的逻辑有些错误,当头部或者尾部真的要刷新的时候,我们就任务其值为1,否则为0,这样在刷新的时候就确保只有一个部位刷新。
把源码贴出来:
package a6he.android.yzz.com.myrecycleview;
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by yzz on 2017/2/26 0026.
*/
public class YzzRecycleView extends RecyclerView {
private View head;
private View foot;
private boolean isNeedHeadFresh = false;
private boolean isNeedFootFresh = false;
//刷新的状态
public static final int STATE_NOMAL = 0;
public static final int STATE_FRESHING = 1;
private int mState = STATE_NOMAL;
private RecyclerView.Adapter<ViewHolder> mAdapter;
private boolean opPenHead = false;
private boolean opFoot = false;
private float mFy = 0;
private OnLoadMoreListener mOnLoadMore;
private Adapter mInnerAdapter;
public static final int HEAD = 0;
public static final int BOTTOM = 1;
private int mRefreshPosition = HEAD - 1;
//刷新界面的高度
public static final int STATIC_HEIGHT = 200;
public YzzRecycleView(Context context) {
super(context);
init();
}
public YzzRecycleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public YzzRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void setMAdapter(RecyclerView.Adapter mAdapter) {
this.mAdapter = mAdapter;
setAdapter(mInnerAdapter);
}
private void init() {
mInnerAdapter = new Adapter();
head = LayoutInflater.from(getContext()).inflate(R.layout.refresh, null);
foot = LayoutInflater.from(getContext()).inflate(R.layout.refresh, null);
addOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
//这里要判断是否是到达顶部和尾部
//当在刷新的时候就不做任何处理
if (mState == STATE_FRESHING) {
return;
}
if (mAdapter == null) {
return;
}
int visibleCount = getLayoutManager().getChildCount();
if (visibleCount > 0 && newState == RecyclerView.SCROLL_STATE_IDLE && isNeedFresh()) {
//判断是否到达顶部
int first = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
if (first == 0 && isNeedHeadFresh) {
opPenHead = true;
}
int last = ((LinearLayoutManager) getLayoutManager()).findLastVisibleItemPosition();
if (last == mAdapter.getItemCount() - 1) {
opFoot = true;
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
}
public void setLayoutManger(final LayoutManager layout, final int spanCount) {
if (layout instanceof GridLayoutManager) {
final GridLayoutManager m = (GridLayoutManager) layout;
m.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (mState == STATE_FRESHING) {
if (position == 0 && mRefreshPosition == HEAD) {
return spanCount;
} else if (mRefreshPosition == BOTTOM && position == getAdapter().getItemCount() - 1) {
return spanCount;
}
}
return 1;
}
});
setLayoutManager(layout);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
mFy = ev.getY();
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent e) {
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
mFy = e.getY();
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
float y = e.getY() - mFy;
loadMore(y);
opPenHead = false;
opFoot = false;
break;
}
return super.onTouchEvent(e);
}
private void loadMore(float x) {
if (x > 50 && opPenHead) {
mState = STATE_FRESHING;
if (mOnLoadMore != null) {
mRefreshPosition = HEAD;
mOnLoadMore.onLoadMore();
notifyData();
}
}
if (x < -50 && opFoot) {
mState = STATE_FRESHING;
if (mOnLoadMore != null) {
mRefreshPosition = BOTTOM;
mOnLoadMore.onLoadMore();
notifyData();
scrollBy(0, STATIC_HEIGHT);
}
}
}
public void setNeedHeadFresh(boolean needHeadFresh) {
isNeedHeadFresh = needHeadFresh;
}
public void setNeedFootFresh(boolean needFootFresh) {
isNeedFootFresh = needFootFresh;
}
public int getHeadCount() {
return mRefreshPosition == HEAD ? 1 : 0;
}
public int getFootCount() {
return mRefreshPosition == BOTTOM ? 1 : 0;
}
public boolean isNeedFresh() {
return isNeedFootFresh || isNeedHeadFresh ? true : false;
}
//玩成的监听
public void complete() {
mState = STATE_NOMAL;
mRefreshPosition = HEAD - 1;
notifyData();
}
public interface OnLoadMoreListener {
void onLoadMore();
}
public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMore) {
this.mOnLoadMore = mOnLoadMore;
}
public void notifyData() {
mInnerAdapter.notifyDataSetChanged();
}
/**
* BaseAdapter,控制头尾的刷新视图
* <p/>
* RecyclerView.INVALID_TYPE:是-1,这里作为头部视图
*/
class Adapter extends RecyclerView.Adapter<ViewHolder> {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (mState == STATE_NOMAL) {
return mAdapter.onCreateViewHolder(parent, viewType);
}
if (viewType == INVALID_TYPE && isNeedHeadFresh && mRefreshPosition == HEAD) {
return new ViewHolder(head);
} else if (viewType == INVALID_TYPE - 1 && isNeedFootFresh && mRefreshPosition == BOTTOM) {
return new ViewHolder(foot);
}
return mAdapter.onCreateViewHolder(parent, viewType);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (mState == STATE_NOMAL) {
mAdapter.onBindViewHolder(holder, position);
return;
}
if (position >= 0 && position < getHeadCount()) {
return;
}
if (mAdapter != null) {
int real = position - getHeadCount();
if (real < mAdapter.getItemCount()) {
mAdapter.onBindViewHolder(holder, real);
}
}
}
@Override
public int getItemCount() {
if (mState == STATE_NOMAL) {
return mAdapter.getItemCount();
}
return mAdapter == null ? getHeadCount() + getFootCount() : +getHeadCount() + getFootCount() + mAdapter.getItemCount();
}
@Override
public int getItemViewType(int position) {
if (mState == STATE_NOMAL) {
return mAdapter.getItemViewType(position);
}
if (getHeadCount() > 0 && position < 1) {
return INVALID_TYPE;
}
int real = position - getHeadCount();
if (real < mAdapter.getItemCount()) {
return mAdapter.getItemViewType(real);
}
return INVALID_TYPE - 1;
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
}
}
}