您的位置:首页 > 移动开发 > Android开发

换一种思路--使用behavior实现recyclerView的下拉加载更多

2017-04-20 10:25 507 查看
下面是整体效果图,虽然很简单,不过功能还是是完善的。。。。



Android 5.0退出 MD风格之后,到现在可以看到很多应用都用上了各种材料设计风格,其中recyclerView应该在很大程度上已经取代了listView,而我们以前常用的上啦刷新和下拉加载也就在所有应用上都成了必不可少的一部分了,下拉刷新我们就不说了 ,毕竟谷歌已经提供了SwipeRefreshLayout。那么我们就来聊聊下拉加载吧.

1.网上大部分实现的方案都是下面这样的:

mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {

@Override
public void onScrollStateChanged(RecyclerView recyclerView,
int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE
&& lastVisibleItem + 1 == adapter.getItemCount()) {
mSwipeRefreshWidget.setRefreshing(true);
handler.sendEmptyMessageDelayed(0, 3000);
}
}

@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
lastVisibleItem = mLayoutManager.findLastVisibleItemPosition();
}
});


这里就不多做介绍了,实现方式和listView的实现原理差不多,通过最后一个可见item的position和item的总数来判断是不是到了最后一个item了。

2.我们今天来实现的方式呢略有一点不一样,首先你可能需要有点CoordinatorLayout和behavior的知识,如果你这块还不是很懂的话可以看看http://blog.csdn.net/yanzhenjie1003/article/details/52205665

那么接下来,我们来看看我们的实现思路,在这之前我想说下就是以下的东西我只是提供了简单的实现想法,在项目中的话,你应该还有更好的封装:

第一步:我们自定义一个ViewGroup用来响应我们的behavior(踩坑:建议直接继承ViewGroup来自定义,因为其实我们的加载更多布局是隐藏在屏幕下方的,而不是一个recyclerView的item,那么这时候当你继承linearlayout的时候,隐藏在下方没有出现的布局将被裁剪掉,然后你就发现我们的加载更多不见了)

@CoordinatorLayout.DefaultBehavior(LoadMore.class)//**这个就是关联到我们自定义的behavior**
public class LoadMoreLayout extends ViewGroup {
private FrameLayout mBottomView;
private IStartLoad mStartLoad;

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

public LoadMoreLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public LoadMoreLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mBottomView = new FrameLayout(getContext());
}
//自定义测量。。。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int hei = 0;
for (int i = 0; i < getChildCount(); i++) {
View childAt = getChildAt(i);
measureChild(childAt, widthMeasureSpec, heightMeasureSpec);
hei += childAt.getMeasuredHeight();
}
setMeasuredDimension(getDefaultSize(widthMeasureSpec, 0), hei);
}
//布局,从上往下排列(这也意味着我们的 recyclerView应该是在第一个布局的,不够完善,请根据自己需求来重写)
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
for (int i = 0; i < getChildCount(); i++) {
View childAt = getChildAt(i);
View pre = getPreChild(i - 1);
if (pre == null) {
childAt.layout(0, 0, r, childAt.getMeasuredHeight());
} else {
childAt.layout(0, pre.getBottom(), r, pre.getBottom() + childAt.getMeasuredHeight());
}
}
}

@Override
protected void onFinishInflate() {
super.onFinishInflate();
addView(mBottomView);//将我们的底部加载更多布局添加进来
}

private View getPreChild(int i) {
if (i < 0) {
return null;
} else {
return getChildAt(i);
}
}
public void setBottomView(View view){
mBottomView.addView(view);//我们可以自定义 加载更多布局 传进来
}
public int getBottomHeight() {
return mBottomView.getHeight();
}

public void startLoad() {
if(mStartLoad!=null){
mStartLoad.startLoad();//开始加载更多的回调
}
}

public void reset() {
scrollBy(0, -getScrollY());//其实这就是简单的隐藏加载更多布局
}

public IStartLoad getStartLoad() {
return mStartLoad;
}

public void setStartLoad(IStartLoad mStartLoad) {
this.mStartLoad = mStartLoad;
}

public interface IStartLoad {
void startLoad();
}


第二步 好了,我们来看看我们behavior是怎么写的吧:

import android.support.design.widget.CoordinatorLayout;
import android.view.View;

/**
* create by liuhuang at 2017/4/19
*/
public class LoadMore extends CoordinatorLayout.Behavior {
//这应该就是一个很简单的behavior了,也没什么好说的 ,如果不懂的话可以先去度娘问问behavior的实现
//我们这里的整体思路也是当recyclerView滑动到最底部的时候,
//去scroll我们的LoadMoreLayout来显示加载更多的布局
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
return child instanceof LoadMoreLayout;
}

@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
int scrollY = child.getScrollY();
//        System.out.println("=="+scrollY+"=="+dy);
if (scrollY > 0 && dy < 0) {
int canScrollY = getCanScrollY(scrollY, dy);
child.scrollBy(0, -canScrollY);
consumed[1] = canScrollY;
} else if (scrollY < 0 && dy > 0) {
int canScrollY = getCanScrollY(scrollY, dy);
child.scrollBy(0, canScrollY);
consumed[1] = canScrollY;
}
}

@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
//        System.out.println(dyConsumed + "===" + dyUnconsumed);
if (dyConsumed == 0 && dyUnconsumed > 0) {
//滑到底部了
if (child instanceof LoadMoreLayout) {
LoadMoreLayout layout = (LoadMoreLayout) child;
int scrollY = child.getScrollY();
int max = layout.getBottomHeight() - scrollY;
int canScrollY = getCanScrollY(max, dyUnconsumed);
child.scrollBy(0, canScrollY);
if (canScrollY != 0) {
layout.startLoad();
}
}
}

}
private int getCanScrollY(int needY, int provideY) {
int absNeedY = Math.abs(needY);
int absProvideY = Math.abs(provideY);
if (absProvideY >= absNeedY) {
return absNeedY;
} else {
return absProvideY;
}
}
}


好吧,这篇博文主要还是想写一个思路,过多的也不说了,希望这篇文章对你有帮助,这是完整的demo链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐