美文网首页Android 学习待修改-精通安卓Android技术研究
[49→100]那些年用过的下拉刷新、上拉加载更多的库

[49→100]那些年用过的下拉刷新、上拉加载更多的库

作者: 沉思的Panda | 来源:发表于2016-06-13 22:48 被阅读3942次

    移动端开发,不联网的App少之又少,所以下拉刷新数据、上拉加载更多数据作为一个基础功能,相关的库层出不穷,这里就记录一下曾经用过的库吧,希望对大家有用。

    一、 Android-PullToRefresh

    这是最经典的下拉刷新库了。在github上有6952个Star、4746个Fork。在用eclipse开发Android的时代,是必备使用的库之一。

    集成方式也很简单。

    1. eclipse导入lib 源码
    2. 显示代码:
    <!--
      The PullToRefreshListView replaces a standard ListView widget.
      The ID CAN NOT be @+id/android:list
    -->
    <com.handmark.pulltorefresh.library.PullToRefreshListView
        android:id="@+id/pull_to_refresh_listview"
        android:layout_height="fill_parent"
        android:layout_width="fill_parent" />
    
    1. 控制代码:
    // Set a listener to be invoked when the list should be refreshed.
    PullToRefreshListView pullToRefreshView = (PullToRefreshListView) findViewById(R.id.pull_to_refresh_listview);
    pullToRefreshView.setOnRefreshListener(new OnRefreshListener<ListView>() {
        @Override
        public void onRefresh(PullToRefreshBase<ListView> refreshView) {
            // Do work to refresh the list here.
            new GetDataTask().execute();
        }
    });
    
    private class GetDataTask extends AsyncTask<Void, Void, String[]> {
        ...
        @Override
        protected void onPostExecute(String[] result) {
            // Call onRefreshComplete when the list has been refreshed.
            pullToRefreshView.onRefreshComplete();
            super.onPostExecute(result);
        }
    }
    

    遗憾的是,这个项目不再维护,最后一次更新日期为2013年2月2号,在Android开发已经进化到gradle一行导包的时代,只能放弃它了。

    二、android-Ultra-Pull-To-Refresh

    这是国内Android开发大神廖祜秋开发的一个开源库。特点是内置各种下拉刷新交互风格。

    • 下拉刷新(iOS风格)

      <div> </div>
    • 释放刷新(经典风格)

      <div> </div>
    • 刷新时,头部保持(新浪微博)

    • 刷新时,头部不保持(微信朋友圈)

    • 自动刷新,进入界面时自动刷新

      </div>

    集成方式很简单:

    1. 一行导包
    compile 'in.srain.cube:ultra-ptr:1.0.11'
    
    1. 界面逻辑:
    <in.srain.cube.views.ptr.PtrFrameLayout
        android:id="@+id/store_house_ptr_frame"
        xmlns:cube_ptr="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        cube_ptr:ptr_resistance="1.7"
        cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
        cube_ptr:ptr_duration_to_close="300"
        cube_ptr:ptr_duration_to_close_header="2000"
        cube_ptr:ptr_keep_header_when_refresh="true"
        cube_ptr:ptr_pull_to_fresh="false" >
    <LinearLayout
            android:id="@+id/store_house_ptr_image_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/cube_mints_333333"
            android:clickable="true"
            android:padding="10dp">
            <in.srain.cube.image.CubeImageView
                android:id="@+id/store_house_ptr_image"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>
    </in.srain.cube.views.ptr.PtrFrameLayout>
    
    1. 控制逻辑:
    ptrFrame.setPtrHandler(new PtrHandler() {
        @Override
        public void onRefreshBegin(PtrFrameLayout frame) {
            frame.postDelayed(new Runnable() {
                @Override
                public void run() {
                    ptrFrame.refreshComplete();
                }
            }, 1800);
        }
    
        @Override
        public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
            // 默认实现,根据实际情况做改动
            return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);
        }
    });
    

    相关原理可以参考作者写的文档——我眼中的下拉刷新

    遗憾的是这个库不支持上拉加载更多,作者有提供一个解决方案——android-cube-app,但是这个解决方案是一个demo,而不是内嵌在Ultra-Pull-To-Refresh中,不符合一行导包的原则了。

    三、BGARefreshLayout-Android

    这个库同时支持下拉刷新和上拉加载更多,集成也很简单:

    1. 一行导包
    dependencies {
        compile 'com.android.support:recyclerview-v7:latestVersion'
        // 记得添加nineoldandroids
        compile 'com.nineoldandroids:library:2.4.0'
        compile 'cn.bingoogolapple:bga-refreshlayout:latestVersion@aar'
    }
    
    1. 界面逻辑:
    <cn.bingoogolapple.refreshlayout.BGARefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/rl_modulename_refresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!-- 内容控件 -->
        <AnyView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />
    </cn.bingoogolapple.refreshlayout.BGARefreshLayout>
    
    1. 控制逻辑:
    // 让activity或者fragment实现BGARefreshLayoutDelegate接口
    public class ModuleNameActivity extends AppCompatActivity implements BGARefreshLayout.BGARefreshLayoutDelegate {
        private BGARefreshLayout mRefreshLayout;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_moudlename);
            initRefreshLayout();
        }
        private void initRefreshLayout(BGARefreshLayout refreshLayout) {
            mRefreshLayout = (BGARefreshLayout) findViewById(R.id.rl_modulename_refresh);
            // 为BGARefreshLayout设置代理
            mRefreshLayout.setDelegate(this);
            // 设置下拉刷新和上拉加载更多的风格     参数1:应用程序上下文,参数2:是否具有上拉加载更多功能
            BGARefreshViewHolder refreshViewHolder = new XXXImplRefreshViewHolder(this, true))
            // 设置下拉刷新和上拉加载更多的风格
            mRefreshLayout.setRefreshViewHolder(refreshViewHolder);
            // 为了增加下拉刷新头部和加载更多的通用性,提供了以下可选配置选项  -------------START
            // 设置正在加载更多时不显示加载更多控件
            // mRefreshLayout.setIsShowLoadingMoreView(false);
            // 设置正在加载更多时的文本
            refreshViewHolder.setLoadingMoreText(loadingMoreText);
            // 设置整个加载更多控件的背景颜色资源id
            refreshViewHolder.setLoadMoreBackgroundColorRes(loadMoreBackgroundColorRes);
            // 设置整个加载更多控件的背景drawable资源id
            refreshViewHolder.setLoadMoreBackgroundDrawableRes(loadMoreBackgroundDrawableRes);
            // 设置下拉刷新控件的背景颜色资源id
            refreshViewHolder.setRefreshViewBackgroundColorRes(refreshViewBackgroundColorRes);
            // 设置下拉刷新控件的背景drawable资源id
            refreshViewHolder.setRefreshViewBackgroundDrawableRes(refreshViewBackgroundDrawableRes);
            // 设置自定义头部视图(也可以不用设置)     参数1:自定义头部视图(例如广告位), 参数2:上拉加载更多是否可用
            mRefreshLayout.setCustomHeaderView(mBanner, false);
            // 可选配置  -------------END
        }
        @Override
        public void onBGARefreshLayoutBeginRefreshing(BGARefreshLayout refreshLayout) {
            // 在这里加载最新数据
    
            if (mIsNetworkEnabled) {
                // 如果网络可用,则加载网络数据
                new AsyncTask<Void, Void, Void>() {
    
                    @Override
                    protected Void doInBackground(Void... params) {
                        try {
                            Thread.sleep(MainActivity.LOADING_DURATION);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return null;
                    }
    
                    @Override
                    protected void onPostExecute(Void aVoid) {
                        // 加载完毕后在UI线程结束下拉刷新
                        mRefreshLayout.endRefreshing();
                        mDatas.addAll(0, DataEngine.loadNewData());
                        mAdapter.setDatas(mDatas);
                    }
                }.execute();
            } else {
                // 网络不可用,结束下拉刷新
                Toast.makeText(this, "网络不可用", Toast.LENGTH_SHORT).show();
                mRefreshLayout.endRefreshing();
            }
        }
    
        @Override
        public boolean onBGARefreshLayoutBeginLoadingMore(BGARefreshLayout refreshLayout) {
            // 在这里加载更多数据,或者更具产品需求实现上拉刷新也可以
    
            if (mIsNetworkEnabled) {
                // 如果网络可用,则异步加载网络数据,并返回true,显示正在加载更多
                new AsyncTask<Void, Void, Void>() {
    
                    @Override
                    protected Void doInBackground(Void... params) {
                        try {
                            Thread.sleep(MainActivity.LOADING_DURATION);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        return null;
                    }
    
                    @Override
                    protected void onPostExecute(Void aVoid) {
                        // 加载完毕后在UI线程结束加载更多
                        mRefreshLayout.endLoadingMore();
                        mAdapter.addDatas(DataEngine.loadMoreData());
                    }
                }.execute();
    
                return true;
            } else {
                // 网络不可用,返回false,不显示正在加载更多
                Toast.makeText(this, "网络不可用", Toast.LENGTH_SHORT).show();
                return false;
            }
        }
        // 通过代码方式控制进入正在刷新状态。应用场景:某些应用在activity的onStart方法中调用,自动进入正在刷新状态获取最新数据
        public void beginRefreshing() {
            mRefreshLayout.beginRefreshing();
        }
        // 通过代码方式控制进入加载更多状态
        public void beginLoadingMore() {
            mRefreshLayout.beginLoadingMore();
        }
    }
    

    但这个库有一个严重的bug

    正在刷新或加载更多时,用户上下滑动不会让下拉刷新视图和加载更多视图跟着滑动

    这一点在网络慢的时候,非常影响用户体验

    四、CommonPullToRefresh

    这个库基于android-Ultra-Pull-To-Refresh,封装了加载更多的逻辑,而且还支持Android最新推出的下拉控件** SwipeRefreshLayout**

    SwipeRefreshLayout

    集成步骤同样简单:

    1. 一行导包
    compile 'com.chanven.lib:cptr:1.0.0'
    
    1. 界面逻辑
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <com.chanven.lib.cptr.PtrClassicFrameLayout
            android:id="@+id/test_list_view_frame"
            xmlns:cube_ptr="http://schemas.android.com/apk/res-auto"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#f0f0f0"
            cube_ptr:ptr_resistance="1.7"
            cube_ptr:ptr_ratio_of_header_height_to_refresh="1.2"
            cube_ptr:ptr_duration_to_close="200"
            cube_ptr:ptr_duration_to_close_header="1000"
            cube_ptr:ptr_keep_header_when_refresh="true"
            cube_ptr:ptr_pull_to_fresh="false">
    
            <ListView
                android:id="@+id/test_list_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/white"
                android:choiceMode="singleChoice"
                android:divider="#b0b0b0"
                android:dividerHeight="0.1dp"
                android:fadingEdge="none"
                android:scrollbarStyle="outsideOverlay"/>
        </com.chanven.lib.cptr.PtrClassicFrameLayout>
    </LinearLayout>
    
    1. 控制逻辑
      这一块可以使用android-Ultra-Pull-To-Refresh的方式,也可以使用** SwipeRefreshLayout**的方式,看需求了。

    我现在选择的下拉刷新库就是CommonPullToRefresh,目前使用中还没有发现问题。

    Panda
    2016-06-13

    相关文章

      网友评论

      • 80ac41b8844a:CommonPullToRefresh 楼主有这个问题吗,.我下拉刷新的时候,是网络请求完成后,设置refreshComplete(),然后更新数据,.当网络请求很快的时候,界面上的数据已经更新完毕了,但是
        refreshComplete()还是在loading,有个延迟才关闭header,
      • _一脸嫌弃:PullToRefresh确实经典,但有一个非常致命的问题,当数据量过大的时候或者布局较复杂的时候,下拉刷新会有"断层"的现象,没办法解决
      • kidz:感谢分享
      • 沉思的Panda:你可以看看这个 http://www.xuebuyuan.com/2191777.html
        b0560b63b4cc:@沉思的Panda 最外层是下拉刷新框架,里面是一个scrollview,scrollview中嵌套了viewpager和listview,viewpager在界面顶部,listview在viewpager下面。
        沉思的Panda:@人心弗远 你是指用Listview嵌套viewpager吗?还是viewpager嵌套Listview啊?
        b0560b63b4cc:@沉思的Panda 不是因为Scrollview嵌套listview的问题,是嵌套了轮播控件后,左右滑动viewpager与下拉刷新冲突,怎么解决,跪求楼主了,想了好久没能解决。
      • b0560b63b4cc:该框架嵌套viewpager后滑动冲突,怎么解决,楼主??,试了几种方法都不行哦。。。。。
      • f3f4672ef98e:CommonPullToRefresh这个库也有问题啊,在Fragment里面用,直接在mPtrFrame.setLoadMoreEnable(true)那里报java.lang.IllegalStateException: unSupported contentView !楼主怎么破啊?
        沉思的Panda:@f3f4672ef98e 哦,你可以到github上给作者反馈,我使用过程中没有碰到这个问题
        f3f4672ef98e:@沉思的Panda 布局文件com.chanven.lib.cptr.PtrClassicFrameLayout中只有一个ScrollView子元素 ScrollView里面只有一个LinearLayout 然后把所有的内容放到这个LinearLayout中 就这样的一个布局 有问题??
        沉思的Panda:@f3f4672ef98e 应该是contentView的个数超过2了吧
      • 菲利柯斯:CommonPullToRefresh这个库,博主在用的时候,有没有点击footer的时候会触发item的点击事件?
        在分页没有数据的时候使用ptr.loadMoreComplete(false);进行提交的吗?
        在第一页的时候,当数据不满一屏的时候怎么去掉footer的显示?
        沉思的Panda:@菲利柯斯 作者在1.1里面增加了两个接口来处理这种情形
        ```
        是否需要加载更多 默认false mPtrFrame.setLoadMoreEnable(true)
        是否自动加载 默认true mPtrFrame.setAutoLoadMoreEnable(true)
        ```
        菲利柯斯:@kyolee footer的显示我把他的源码下载下来,再AS引用的本地的lib,修改一下他的源码,算是解决了,但是不知道完美不,现在没有出问题。
        item的点击事件,只能去加判断了,根据list的size去判断。
        8797e0d3f45b:@菲利柯斯 同样的问题你解决了么!!!~~
      • hackest:最后亮了
      • 大凡:👏👏👏👏👏
      • 浮生如茶2016:写的不错,赞一个!

      本文标题:[49→100]那些年用过的下拉刷新、上拉加载更多的库

      本文链接:https://www.haomeiwen.com/subject/kwnydttx.html