您的位置:首页 > 其它

RecyclerView 下拉刷新上拉加载更多

2016-03-23 10:13 459 查看
先附上效果



RecyclerView的封装如下

[java] view
plain copy

package com.byzk.www.recyclerviewpackage;

import android.content.Context;

import android.support.v7.widget.GridLayoutManager;

import android.support.v7.widget.LinearLayoutManager;

import android.support.v7.widget.RecyclerView;

import android.support.v7.widget.StaggeredGridLayoutManager;

import android.util.AttributeSet;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import jp.wasabeef.recyclerview.animators.adapters.SlideInBottomAnimationAdapter;

/**

* Author: zhuliyuan

* Time: 下午 3:26

*/

public class RefreshRecyclerView extends RecyclerView {

private AutoLoadAdapter autoLoadAdapter;

public RefreshRecyclerView(Context context) {

this(context, null);

}

public RefreshRecyclerView(Context context, AttributeSet attrs) {

this(context, attrs, 0);

}

public RefreshRecyclerView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs, defStyle);

init();

}

private boolean isLoadingMore = false;//是否正在加载更多

private int loadMorePosition = -1;//记录最后刷新位置

private OnLoadDataListener loadDataListener;//加载数据监听

private boolean isLoadMoreEnable = false;//是否允许加载更多

private int footerResource;//脚布局

private void init() {

setOnScrollListener(new OnScrollListener() {

@Override

public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

super.onScrollStateChanged(recyclerView, newState);

int lastVisiblePosition = getLastVisiblePosition();

int itemCount = getAdapter().getItemCount();

if (lastVisiblePosition + 4 >= itemCount - 1 && !isLoadingMore && isLoadMoreEnable) {

isLoadingMore = true;//设置正在刷新

loadMorePosition = itemCount - 1;//记录最后刷新位置

if (loadDataListener != null) {

loadDataListener.pullUpRefresh();

}

}

}

});

}

@Override

public void setAdapter(Adapter adapter) {

autoLoadAdapter = new AutoLoadAdapter(new SlideInBottomAnimationAdapter(adapter));//添加动画

super.setAdapter(autoLoadAdapter);

}

/**

* 设置是否允许加载更多

*

* @param isEnable

*/

public void setLoadMoreEnable(boolean isEnable) {

this.isLoadMoreEnable = isEnable;

}

/**

* 设置脚布局

*/

public void setFooterResource(int footerResource) {

this.footerResource = footerResource;

}

/**

* 加载完成

*

*/

private void loadMoreComplete() {

this.isLoadingMore = false;

}

/**

* 获得最后一条可见

*

* @return

*/

private int getLastVisiblePosition() {

LayoutManager layoutManager = getLayoutManager();

int position = -1;

if (layoutManager instanceof LinearLayoutManager) {

position = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();

} else if (layoutManager instanceof GridLayoutManager) {

position = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();

} else if (layoutManager instanceof StaggeredGridLayoutManager) {

int[] positions = ((StaggeredGridLayoutManager) layoutManager).findLastVisibleItemPositions(null);//返回最后可见的一行position

for (int i = 0; i < positions.length - 1; i++) {

position = Math.max(positions[i], positions[i + 1]);

}

}

return position;

}

/**

* 上拉刷新回调

*

* @param listener

*/

public void setOnLoadDataListener(OnLoadDataListener listener) {

this.loadDataListener = listener;

}

public interface OnLoadDataListener {

void pullUpRefresh();//上拉刷新

}

/**

* 刷新更多数据

*/

public void notifyMoreData() {

getAdapter().notifyItemRemoved(loadMorePosition);

loadMoreComplete();

}

/**

* 刷新最新数据

*/

public void notifyNewData(){

getAdapter().notifyDataSetChanged();

}

public class AutoLoadAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private Adapter dataAdapter;//数据adapter

private final int TYPE_NORMAL = 0;//正常

private final int TYPE_FOOTER = 1;//底部布局

public AutoLoadAdapter(RecyclerView.Adapter adapter) {

this.dataAdapter = adapter;

}

@Override

public int getItemViewType(int position) {

if (position == getItemCount() - 1 && isLoadMoreEnable) {

return TYPE_FOOTER;

}

return TYPE_NORMAL;

}

@Override

public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

ViewHolder holder = null;

if (viewType == TYPE_FOOTER) {//脚部

holder = new FooterViewHolder(LayoutInflater.from(parent.getContext()).inflate(footerResource, parent, false));

} else if (viewType == TYPE_NORMAL) {//数据

holder = dataAdapter.onCreateViewHolder(parent, viewType);

}

return holder;

}

@Override

public void onBindViewHolder(ViewHolder holder, int position) {

int itemViewType = getItemViewType(position);

if (itemViewType != TYPE_FOOTER) {

dataAdapter.onBindViewHolder(holder, position);

}

}

@Override

public int getItemCount() {

if (dataAdapter.getItemCount() != 0) {

int count = dataAdapter.getItemCount();

if (isLoadMoreEnable)//增加了脚布局

count++;

return count;

}

return 0;

}

public class FooterViewHolder extends RecyclerView.ViewHolder {

public FooterViewHolder(View itemView) {

super(itemView);

}

}

}

}

这里只封装了上拉加载更多,自己写了个adpter壳子,当允许上拉加载更多的时候并且为最后条时显示脚布局,其他时候数据都来源于自己写的DataAdapter,下拉刷新可以按同样原理实现.这里我就直接套的SwipeRefreshLayout了.

提供数据Adapter如下

[java] view
plain copy

package com.byzk.www.recyclerviewpackage;

import android.support.v7.widget.RecyclerView;

import android.view.LayoutInflater;

import android.view.View;

import android.view.ViewGroup;

import android.widget.TextView;

import java.util.List;

/**

* Author: zhuliyuan

* Time: 下午 5:36

*/

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

private List<String> dataList;

@Override

public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

MyViewHolder myViewHolder = new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false));

return myViewHolder;

}

@Override

public void onBindViewHolder(MyAdapter.MyViewHolder holder, int position) {

holder.tv.setText(dataList.get(position));

}

public class MyViewHolder extends RecyclerView.ViewHolder{

private TextView tv;

public MyViewHolder(View itemView) {

super(itemView);

tv = (TextView) itemView.findViewById(R.id.tv);

}

}

@Override

public int getItemCount() {

return (dataList == null || dataList.size() == 0)?0:dataList.size();

}

public void setData(List<String> dataList){

this.dataList = dataList;

}

}

item布局如下

[java] view
plain copy

<?xml version="1.0" encoding="utf-8"?>

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:card_view="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="60dp"

android:layout_marginLeft="5dp"

android:layout_marginRight="5dp"

android:clickable="true"

android:foreground="?attr/selectableItemBackground"

card_view:cardBackgroundColor="#0094ff"

card_view:cardCornerRadius="6dp"

card_view:cardElevation="5dp">

<TextView

android:id="@+id/tv"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:text="哈哈哈"

android:textColor="#000" />

</android.support.v7.widget.CardView>

activity中代码如下

[java] view
plain copy

package com.byzk.www.recyclerviewpackage;

import android.os.Bundle;

import android.os.Handler;

import android.support.v4.widget.SwipeRefreshLayout;

import android.support.v7.app.AppCompatActivity;

import android.support.v7.widget.DefaultItemAnimator;

import android.support.v7.widget.LinearLayoutManager;

import java.util.ArrayList;

import java.util.List;

import jp.wasabeef.recyclerview.animators.adapters.AlphaInAnimationAdapter;

import jp.wasabeef.recyclerview.animators.adapters.ScaleInAnimationAdapter;

import jp.wasabeef.recyclerview.animators.adapters.SlideInBottomAnimationAdapter;

public class MainActivity extends AppCompatActivity {

private List<String> dataList = new ArrayList<>();

private RefreshRecyclerView rv;

private MyAdapter myAdapter;

private SwipeRefreshLayout srl;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

init();

}

private void init() {

initView();

initData();

initListener();

}

private void initView() {

srl = (SwipeRefreshLayout) findViewById(R.id.srl);

srl.setColorSchemeResources(android.R.color.holo_red_light, android.R.color.holo_blue_light, android.R.color.holo_green_light);

rv = (RefreshRecyclerView) findViewById(R.id.rv);

rv.setLayoutManager(new LinearLayoutManager(this));

rv.setItemAnimator(new DefaultItemAnimator());

rv.setLoadMoreEnable(true);

rv.setFooterResource(R.layout.item_footer);

myAdapter = new MyAdapter();

rv.setAdapter(myAdapter);

}

private void initData() {

for (int i = 0; i < 20; i++) {

dataList.add("数据" + i);

}

myAdapter.setData(dataList);

rv.notifyNewData();

}

private void initListener() {

rv.setOnLoadDataListener(new RefreshRecyclerView.OnLoadDataListener() {

@Override

public void pullUpRefresh() {

handler.postDelayed(new Runnable() {

@Override

public void run() {

for (int i = 0; i < 10; i++) {

dataList.add("更多数据" + i);

}

myAdapter.setData(dataList);//设置新数据

rv.notifyMoreData();//刷新数据

}

}, 2000);

}

});

srl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {

@Override

public void onRefresh() {

handler.postDelayed(new Runnable() {

@Override

public void run() {

srl.setRefreshing(false);

dataList.add(0, "最新数据");

myAdapter.setData(dataList);//设置新数据

rv.notifyNewData();//刷新数据

}

}, 2000);

}

});

}

private Handler handler = new Handler();

}

下拉刷新用的是v4包中的SwipeRefreshLayout直接包裹在自己封装的RecyclerView的外层,上拉加载更多用的是自己封装的RecyclerView.

接下来是activity中的布局文件

[java] view
plain copy

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context="com.byzk.www.recyclerviewpackage.MainActivity">

<android.support.v4.widget.SwipeRefreshLayout

android:id="@+id/srl"

android:layout_width="wrap_content"

android:layout_height="wrap_content">

<com.byzk.www.recyclerviewpackage.RefreshRecyclerView

android:id="@+id/rv"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

</android.support.v4.widget.SwipeRefreshLayout>

</RelativeLayout>

源码传送门

例子中recyclerview动画地址https://github.com/wasabeef/recyclerview-animators
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: