Android自定义View-下拉刷新-拉到底自动加载-LoadingRefreshLayout

主要实现两个功能,第一个是  实现一个下拉加载更多的效果。第二个是RecyclerView拖动到底自动加载的效果。


功能一:下拉加载更多的效果

特点

  1. 继承于LinearLayout,不用自己实现ViewGroup的测量、布局、绘制。
  2. 可以兼容多种类型的控件,RecyclerView、ListView、ScrollerLayout等。
  3. 解决了事件滑动的冲突。
  4. MarginLayoutParams的topMargin属性,实现View的移动。

实现思路

  1. 实现View的移动方法有很多种,因为移动的View位于布局的最顶部,可以通过MarginLayoutParams的topMargin属性,实现顶部View的移动。下移时,增大该值,上移时减少该值。
  2. LoadingRefreshLayout与嵌套的View可能会存在滑动的冲突,在需要下拉或者上移的时候,拦截滑动事件,重写onInterceptOnTouchEvent()方法,在判断需要拦截时,返回true,在onTouchEvent()方法中实现顶部HeadView的移动操作。
  3. 松手时,需要回到加载状态或者原始状态,这时涉及动画移动,使用ValueAnimator属性动画实现。
  4. 松手后,进入到正在加载状态,需要执行加载的动作,这时调用回调监听器;调用端加载完成后,需要调用加载完成的接口,LoadingRefreshLayout进入到加载完成的状态。

  1.     状态的切换过程。初始状态我们先让Head位于屏幕的上方(不可见的状态),RecyclerView充满屏幕。当手指触碰屏幕到手指的移动时,如果RecyclerView处于显示最顶端Item的状态,且是下滑动作,这是就拦截事件。Head随手指进行上下移动,使用的是Head的MarginLayoutParams的topMargin进行Head位置的变化,这时加载状态有如下:
  • 下拉加载状态:从开始拖动到topMargin的大小从-HeadHeight到0。
  •  松开加载状态:从topMargin的大小等于0,直至松手前。
  •  正在加载状态:松手之后,topMargin的大小等于0,直至加载完毕。
  •  加载完成:topMargin的大小变为-HeadHeight。
效果图



用法

####xml中使用
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android";
    xmlns:app="http://schemas.android.com/apk/res-auto";
    xmlns:tools="http://schemas.android.com/tools";
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.lgf.loadingrrefeshlayout.MainActivity">
    <com.lgf.loadingrrefeshlayout.LoadingRefreshLayout
        android:id="@+id/rl_data_list_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <android.support.v7.widget.RecyclerView
            android:id="@+id/rv_data_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </android.support.v7.widget.RecyclerView>
    </com.lgf.loadingrrefeshlayout.LoadingRefreshLayout>
</android.support.constraint.ConstraintLayout>

#### activity中使用
实现拦截接口,判断拦截的条件

    @Override
    public boolean isAllowToIntercept() {
        boolean allowToPull = false;
        View firstChild = mDataRecyclerView.getChildAt(0);
        if (firstChild != null) {
            RecyclerView.LayoutManager layoutManager = mDataRecyclerView.getLayoutManager();
            LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
            int firstVisiblePosition = linearLayoutManager.findFirstVisibleItemPosition();
            if (firstVisiblePosition == 0 && firstChild.getTop() == 0) {
                allowToPull = true;
            } else {
                allowToPull = false;
            }
        } else {
            allowToPull = true;
        }
        return allowToPull;
    }
设置事件拦截条件判断器
  mLoadingRefreshLayout.setInterceptChecker(this);
实现刷新的回调接口,执行刷新动作
    @Override
    public void onRefresh() {
        refreshData();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mLoadingRefreshLayout.finishLoading();
                loadMoreAdapterWrapper.notifyDataSetChanged();
            }
        }, 2000);
    }
设置回调监听器

mLoadingRefreshLayout.setOnRefreshListener(this);
****************************    我是分割线            **********************************************************


功能二:RecyclerView上拉到底自动加载更多的效果

特点

  1. 使用装饰者模式,装饰RecyclerView.Adapter,在使用时,不需要修改原来的代码,无缝接入,便于维护和扩展。
  2. 可以扩展更多的自定义状态,比如加载失败状态。
实现思路
  1. 实现上拉到底自动加载,需要监听RecyclerView滑动到底部的事件,可继承RecyclerView.OnScrollListener,重写onScrollStateChanged()方法,根据当前的滑动状态和RecyclerView的可见Item的位置,可以判断RecyclerView是否滑动到底部。
  2. 要显示正在加载的提示或者没有更多的提示,可以通过重写RecyclerView.Adapter的getItemViewType()、getItemCount()、onCreateViewHolder()、onBindViewHolder()方法,不同的状态设置不同的ItemViewType;根据不同的ItemViewType,生成不同的ViewHolder,加载不同的布局。
  3. 暴露出状态设置的接口,供调用端使用,实现不同显示状态的切换。
效果图



用法

Activity中使用

使用装饰类LoadMoreAdapterWrapper,进行相关的初始化。

    mDataRecyclerView = (RecyclerView) findViewById(R.id.rv_data_list);
    mDataRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    mRecyclerViewAdapter = new MyRecyclerViewAdapter();
    loadMoreAdapterWrapper = new LoadMoreAdapterWrapper(mRecyclerViewAdapter);
    loadMoreAdapterWrapper.setOnLoadMoreListener(this);
    mDataRecyclerView.setAdapter(loadMoreAdapterWrapper);
实现加载更多的逻辑
    @Override
    public void onLoadMore() {
        loadMoreAdapterWrapper.showLoadMoreView();
        mDataRecyclerView.scrollToPosition(loadMoreAdapterWrapper.getItemCount() -1);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                loadMoreAdapterWrapper.showLoadFailedView();
            }
        }, 5000);
    }
重新加载实现逻辑
    @Override
    public void onRetry() {
        loadMoreAdapterWrapper.showLoadMoreView();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                loadMoreAdapterWrapper.showNoMoreView();
            }
        }, 5000);
    }

GitHub源码:LoadingRefreshLayout源码

喜欢的欢迎star一下,谢谢各位朋友。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值