一个比较完整的RecyclerView上拉下拉控件

以前写过一个上拉下拉的控件,经过改版之后,有了这篇博客,代码更简洁了,容易理解了。
先上xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:id="@+id/id_refresh_layout"
    android:layout_height="match_parent">

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/id_refresh_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/id_loadMore_view"
            android:background="@color/line_grey"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

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

然后重写LinearLayout,

/**
 * @Author Lee
 * @Date 创建时间 2017/11/9
 * @Description 可以时间上拉加载下拉刷新的控件
 * @Version 1.0.0
 */

public class RefreshRecyclerView extends LinearLayout {
    private SwipeRefreshLayout RefreshDataView;//下拉刷新控件
    private RecyclerView LoadMoreDataView;//上拉加载控件
    private int LastVisibleItemPosition;//最后一个可见的item位置
    private int PageIndex = 0;//当前的页码
    private boolean IsCanLoadData = true;//可以加载数据

    public RefreshRecyclerView(Context context) {
        super(context);
        View view = LayoutInflater.from(context).
            inflate(R.layout.refresh_recycler_view, this, true);
        __init(view);
    }

    public RefreshRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        View view = LayoutInflater.from(context).
            inflate(R.layout.refresh_recycler_view, this, true);
        __init(view);
    }

    public RefreshRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        View view = LayoutInflater.from(context).
            inflate(R.layout.refresh_recycler_view, this, true);
        __init(view);
    }
    //初始化控件--双下滑是公司要求,按照自己的方法命名就好
    private void __init(View view) {
        //Google自带的下拉刷新
        RefreshDataView = (SwipeRefreshLayout)view.findViewById(R.id.id_refresh_view);
        RefreshDataView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshData();
            }
        });
        //监听RecyclerView 的Scroll事件
        LoadMoreDataView = (RecyclerView)view.findViewById(R.id.id_loadMore_view);
        LoadMoreDataView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            //网上给的都是有下拉圈圈的,老板要求一个无刷新提示的,不过很菜,下拉快了依旧有卡顿现象,欢迎大神给指点
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
                //这里是网上搜到的判断不同布局最后一个的可见位置的方法--为了方便以后重写
                if (layoutManager instanceof GridLayoutManager) {
                    LastVisibleItemPosition = ((GridLayoutManager)layoutManager).
                        findLastVisibleItemPosition();
                }
                else if (layoutManager instanceof StaggeredGridLayoutManager) {
                    int[] into = new int[((StaggeredGridLayoutManager)layoutManager).
                        getSpanCount()];
                    ((StaggeredGridLayoutManager)layoutManager).findLastVisibleItemPositions(into);
                    LastVisibleItemPosition = findMax(into);
                }
                else {
                    LastVisibleItemPosition = ((LinearLayoutManager)layoutManager).
                        findLastVisibleItemPosition();
                }
                //上拉滑动距离大于0,当然也可以设置更多, 可见位置判断最后一个加1,(因为加了个底部,提示已经没有了)
                if (LastVisibleItemPosition + 1 >= recyclerView.getLayoutManager().getItemCount() 
                    && dy >= 0) {
                    getAndLoadDatas();
                }
            }
        });
    }

    private int findMax(int[] lastPositions) {
        int max = lastPositions[0];
        for (int value : lastPositions) {
            if (value > max) {
                max = value;
            }
        }
        return max;
    }
    //获取方法
    public LRecyclerViewAdapter getAdapter() {
        return (LRecyclerViewAdapter) LoadMoreDataView.getAdapter();
    }
    //提供给使用者设置的方法
    public void setAdapter(LRecyclerViewAdapter adapter) {
        LoadMoreDataView.setAdapter(adapter);
    }

    public void setLayoutManager(LinearLayoutManager layoutManager) {
        LoadMoreDataView.setLayoutManager(layoutManager);
    }
    //加载更多方法
    private void getAndLoadDatas() {
        if (!IsCanLoadData) {
            return;
        }
        IsCanLoadData = false;

        //传入当前的页码
        getAdapter().getDatas(getLoadPageIndex(), new LRecyclerViewAdapter.IOnData() {
            @Override
            public void onData(List datas) {
                //AssertUtil一个判断是否为空的工具类,网上百度一个就行
                if (AssertUtil.isEmpty(datas) && !isFullScreen()) {
                    getAdapter().setFootShow(true);
                }
                else {
                    getAdapter().setFootShow(false);
                }
                RefreshDataView.setRefreshing(false);
                if (AssertUtil.isNotEmpty(datas)) {
                    IsCanLoadData = true;
                    getAdapter().appendData(datas);
                }
            }
        });
    }
    //判断是否满一屏幕的方法
    private boolean isFullScreen() {
        return LoadMoreDataView.computeVerticalScrollExtent() >=
            LoadMoreDataView.computeVerticalScrollRange();
    }

    private int getLoadPageIndex() {
        return ++PageIndex;
    }
    //提供外界刷新自主刷新的方法
    public void refreshData() {
        PageIndex = 0;
        getAdapter().clearData();
        IsCanLoadData = true;
        getAndLoadDatas();
    }
}

上面有详细的注释了;
最后就是adapter,在这里我重新了一下adapter

/**
 * @Author Lee
 * @Date 创建时间 2017/11/9
 * @Description
 * @Version 
 */
public abstract class LRecyclerViewAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder>  {
    private static final int VIEW_TYPE_FOOTER = 0;//加载底部数据
    private static final int VIEW_TYPE_ITEM = 1;//加载普通数据
    private static final int FOOTER_SHOW = 0;//底部显示
    private static final int FOOTER_HIDE = 1;//底部隐藏
    private int NowFooterStatus = FOOTER_HIDE;
    private List<T> LoadData;
    protected LayoutInflater Infalter;

    public LRecyclerViewAdapter(Context context, List<T> loadData) {
        Infalter = LayoutInflater.from(context);
        this.LoadData = loadData;
    }

    //加载布局
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_FOOTER) {
            return new LRecyclerViewAdapter.FooterViewHolder(Infalter.inflate(R.layout.footer_layout, parent, false));
        }
        else if (viewType == VIEW_TYPE_ITEM) {
            return setItemVH(parent);
        }
        return null;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if(getItemViewType(position) == VIEW_TYPE_ITEM) {
            onBindItemViewHolder(holder, position);
        }
        else {
            onBindFooterViewHolder(holder, NowFooterStatus);
        }
    }

    private void onBindFooterViewHolder(RecyclerView.ViewHolder holder, int loadStatus) {
        final LRecyclerViewAdapter.FooterViewHolder footerViewHolder = (LRecyclerViewAdapter.FooterViewHolder)holder;
        if (loadStatus == FOOTER_SHOW) {
            footerViewHolder.mLoadingLayout.setVisibility(View.VISIBLE);
            delayedSetFooterGone(footerViewHolder);
        }
        else {
            footerViewHolder.mLoadingLayout.setVisibility(View.GONE);
        }
    }

    private void delayedSetFooterGone(final LRecyclerViewAdapter.FooterViewHolder footerViewHolder) {
        new Handler().postDelayed(new Runnable() {
            public void run() {
                NowFooterStatus = FOOTER_HIDE;
                footerViewHolder.mLoadingLayout.setVisibility(View.GONE);
            }
        }, 2000);
    }

    //得到总数
    @Override
    public int getItemCount() {
        return LoadData.size() + 1;
    }

    @Override
    public int getItemViewType(int position) {
        if (position + 1 == getItemCount()) {
            return VIEW_TYPE_FOOTER;
        }
        return VIEW_TYPE_ITEM;
    }

    public class FooterViewHolder extends RecyclerView.ViewHolder {
        public LinearLayout mLoadingLayout;

        public FooterViewHolder(View itemView) {

            super(itemView);
            mLoadingLayout = (LinearLayout) itemView.findViewById(R.id.id_loading_layout);
        }
    }

    void setData(List<T> data) {
        LoadData.clear();
        LoadData.addAll(data);
        this.notifyDataSetChanged();
    }

    void appendData(List<T> data) {
        LoadData.addAll(data);
        this.notifyDataSetChanged();
    }

    void clearData() {
        LoadData.clear();
        this.notifyDataSetChanged();
    }

    void setFootShow(boolean show) {
        NowFooterStatus = show ? FOOTER_SHOW : FOOTER_HIDE;
    }

    public interface IOnData<T> {
        void onData(List<T> datas);
    }

    public abstract void onBindItemViewHolder(final RecyclerView.ViewHolder holder, int position);
    public abstract RecyclerView.ViewHolder setItemVH(ViewGroup parent);
    public abstract void getDatas(int pageIndex, final IOnData back);
}

上面这个可以复制过去直接使用,当然你需要继承这个类来重写其中的一些方法。
之后就是最后的步骤了。:

初始化Adapter
DeliverAdapter = new DeliverAddressAdapter(DeliveryAddressListActivity.this, new
    ArrayList<DeliveryAddress>());
//素质三连,初始化,放adapter,放LayoutManager
LayoutManager = new LinearLayoutManager(DeliveryAddressListActivity.this);
RefreshRecycler = (RefreshRecyclerView)findViewById(R.id.receiver);
RefreshRecycler.setAdapter(DeliverAdapter);
RefreshRecycler.setLayoutManager(LayoutManager);

实现自己的adapter就可以了,代码如下:

class DeliverAddressAdapter extends LRecyclerViewAdapter<DeliveryAddress> {
        private List<DeliveryAddress> DeliveryAddress;

        public DeliverAddressAdapter(Context context, List<DeliveryAddress> loadData) {
            super(context, loadData);
            this.DeliveryAddress = loadData;
        }

        @Override
        public void onBindItemViewHolder(RecyclerView.ViewHolder holder,final int position) {
            final DeliverAddressVH deliverAddressVH = (DeliverAddressVH)holder;
            deliverAddressVH.id_da_address.setText(DeliveryAddress.get(position).
                getDa_address());
            deliverAddressVH.id_da_consignee.setText(DeliveryAddress.get(position).
                getDa_consignee());
            deliverAddressVH.id_mobile_phone.setText(DeliveryAddress.get(position).
                getDa_consigneetelephone());

            deliverAddressVH.id_address_del.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (position >= 0 && position < DeliveryAddress.size()) {
                        final int da_id = DeliveryAddress.get(position).getDa_id();
                        DeliveryAddress.remove(position);
                        deleteUserAddress(da_id);
                        if (position == 0) {
                            DeliverAdapter.notifyDataSetChanged();
                        }
                        else {
                            DeliverAdapter.notifyItemRemoved(position);//推荐用这个
                        }
                    }
                }
            });
            deliverAddressVH.id_address_edit.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (position >= 0 && position < DeliveryAddress.size()) {
                        Intent intent = new Intent(DeliveryAddressListActivity.this, 
                            DeliveryAddressEditActivity.class);
                        intent.putExtra("delivery", DeliveryAddress.get(position));
                        startActivityForResult(intent, 1);
                    }
                }
            });
        }

        @Override
        public RecyclerView.ViewHolder setItemVH(ViewGroup parent) {
            return new DeliverAddressVH(Infalter.inflate(R.layout.delivery_address_item, 
                parent, false));
        }

        @Override
        public void getDatas(int pageIndex, IOnData back) {
            refreshdata(pageIndex, back);
        }

        public class DeliverAddressVH extends RecyclerView.ViewHolder {
            TextView id_da_address;
            TextView id_da_consignee;
            TextView id_mobile_phone;
            TextView id_address_del;
            TextView id_address_edit;

            public DeliverAddressVH(View itemView) {
                super(itemView);
                id_da_address = (TextView) itemView.findViewById(R.id.id_da_address);
                id_da_consignee = (TextView) itemView.findViewById(R.id.id_da_consignee);
                id_mobile_phone = (TextView) itemView.findViewById(R.id.id_mobile_phone);
                id_address_del = (TextView) itemView.findViewById(R.id.id_address_del);
                id_address_edit = (TextView) itemView.findViewById(R.id.id_address_edit);
            }
        }
    }

以上的在继承的时候会要求重写,使用的时候两个类可以直接复制,布局文件就自己写吧,毕竟都不一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值