RecyclerView 下拉刷新上拉加载更多

这几天研究了下RecyclerView的使用和封装,发现还是蛮好用的,现在把学习成果分享给大家,主要是关于上拉刷新的封装

先附上效果

RecyclerView 下拉刷新上拉加载更多_第1张图片



RecyclerView的封装如下

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如下

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布局如下

<?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中代码如下

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中的布局文件

<?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


如果有什么写的不好的地方希望大家指出,互相讨论学习,谢谢!微笑微笑微笑


你可能感兴趣的:(RecyclerView,下拉刷新上拉加载更多)