PracticalRecyclerView

Introduction: 封装 RecyclerView, 打造为一个非常实用的开发工具 , 添加一些开发中常用的功能 , 例如下拉刷新, 分页, 自动加载 , 加载错误等等
More: Author   ReportBugs   
Tags:
recyclerview-

Encapsulation RecyclerView, to create for the development of a very practical tool, add some commonly used in the development of function, such as drop-down refresh, paging, automatic loading, loading error, etc.More new functions will gradually add...

标签(空格分隔): Android RecyclerView


对 RecyclerView 的一个封装,添加一些实用的功能

主要功能:

  • 下拉刷新,使用默认的下拉刷新控件
  • 页面加载数据过程中显示 LoadingView
  • 页面加载数据出错时显示 ErrorView
  • 页面数据大小为 0 时显示 EmptyView
  • 自动加载,当页面到底部或者当前页面显示不全时,自动加载其余数据,并显示 LoadMoreView
  • 加载更多时出错自动停止加载更多,并显示 LoadMoreFailedView
  • 没有更多数据加载时,显示 NoMoreView
  • 支持 Header View 和 Footer View
  • 除下拉刷新以外,其余 View 均可自定义
  • 支持多种 Item 类型
  • 支持 GridLayout 和瀑布流

2016-10-11 更新:

  • 新增动态显示或关闭 NoMoreView,LoadMoreView,LoadMoreFailedView 功能
  • 新增打开或关闭自动加载功能
  • 新增手动触发加载 demo

2016-10-17 更新:

  • 增加获取 RecyclerView 接口
    public RecyclerView get() {
            return mRecyclerView;
    }
  • 增加拖拽功能与 demo

2016-10-18 更新:

  • 向下支持到 API 11(android 3.0)
  • AbstractAdapter 增加更多操作数据接口, 如:
    public void clearData() {}

    public void clearHeader() {}

    public void clearFooter() {}

    public void insert(){}

    public void insertBack(){}

    //等等
  • 增加 ExpandItemList demo

2016-11-7 更新:

  • 新增添加单个数据接口 void add(T item);

2017-1-22 更新

  • 修复需要滑动两次才能显示 loadmore 的 bug.

效果图

使用方式:

1.添加 Gradle 依赖

Download

    dependencies{
            compile 'zlc.season:practicalrecyclerview:1.1.5'
    }

2.在布局文件中添加 PracticalRecyclerView


     <zlc.season.practicalrecyclerview.PracticalRecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:loading_layout="@layout/default_loading_layout" //可以自定义,也可以不设置使用默认的布局
        app:empty_layout="@layout/default_empty_layout"     //以下属性同样不设置即为使用默认的布局
        app:error_layout="@layout/default_error_layout"
        app:load_more_layout="@layout/default_load_more_layout"
        app:no_more_layout="@layout/default_no_more_layout"
        app:load_more_failed_layout="@layout/default_load_more_failed_layout"/>

3.添加代码

首先定义一个 POJO 类, 并实现 ItemType 接口:

   class NormalBean implements ItemType {
       String mImg;
       String mTitle;
       String mContent;

       NormalBean(String img, String title, String content) {
           mImg = img;
           mContent = content;
           mTitle = title;
       }

       @Override
       public int itemType() {
           return 0;
       }
   }

这里返回的 item type 表示是 item 的类型, 如果列表只有一种类型的 item, 那么返回 0 就可以了, 如果有多种 item, 则对应类型的 item 返回对应类型的 item type. 这里简单的返回 0 .

接着定义 ViewHolder, 继承自 AbstractViewHolder, 并提供泛型参数:

   class NormalViewHolder extends AbstractViewHolder<NormalBean> {
       @BindView(R.id.head)
       ImageView mHead;
       @BindView(R.id.title)
       TextView mTitle;
       @BindView(R.id.content)
       TextView mContent;

       private Context mContext;

       NormalViewHolder(ViewGroup parent) {
           super(parent, R.layout.normal_item); //与对应的 item layout 进行绑定.
           mContext = parent.getContext();      //如果 viewholder 需要 context,在这里获取.
           ButterKnife.bind(this, itemView);    //这里使用了 butterknife 进行控件绑定,也可以手写                                             // itemView.findViewById()来获取对应的控件.
       }

       @Override
       public void setData(NormalBean data) {
           Picasso.with(mContext).load(Uri.parse(data.mImg)).into(mHead);
           mTitle.setText(data.mTitle);
           mContent.setText(data.mContent);
       }
   }

在 Viewholder 中进行 View 的创建和绑定, 如果需要绑定按钮的单击事件或者其他的一些事件, 在此处进行再好不过了.

接下来创建 Adatper, 继承自 AbstractAdapter, 并提供泛型参数:

   class SingleItemAdapter extends AbstractAdapter<NormalBean, NormalViewHolder> {

       @Override
       protected NormalViewHolder onNewCreateViewHolder(ViewGroup parent, int viewType) {
           return new NormalViewHolder(parent);
       }

       @Override
       protected void onNewBindViewHolder(NormalViewHolder holder, int position) {
           holder.setData(get(position));
       }
   }

adapter 类中非常简洁, 只需要在 onNewCreateViewHolder()中创建 ViewHolder, 在 onNewBindViewHolder()中调用 viewholder 的 setData()即可, 这样 adapter 和 viewholder 的逻辑就分离开来,互不干扰.

最后,在 Activity 或者 Fragment 中进行最后的配置:

   PracticalRecyclerView mRecycler;
   private SingleItemAdapter mAdapter = new SingleItemAdapter();
   ...
   mRecycler.setLayoutManager(new LinearLayoutManager(this));
   mRecycler.setAdapterWithLoading(mAdapter);
   mRecycler.setRefreshListener(new PracticalRecyclerView.OnRefreshListener() {
               @Override
               public void onRefresh() {
                   mPresenter.loadData(true);
               }
           });
   mRecycler.setLoadMoreListener(new PracticalRecyclerView.OnLoadMoreListener() {
               @Override
               public void onLoadMore() {
                   mPresenter.loadData(false);
               }
           });
   ...
   //更多详细代码请下载 demo 查看

4.添加 Header 和 Footer

要添加 Header 和 Footer, 可以选择实现 SectionItem 接口, 或者继承 SectionItemImpl, 如下所示:

   class Header implements SectionItem {
           @BindView(R.id.banner_guide_content)
           BGABanner mBanner;

           @Override
           public View createView(ViewGroup parent) {
               View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.header_item, parent, false);
               ButterKnife.bind(this, view);
               return view;
           }

           @Override
           public void onBind() {
               mBanner.setAdapter(new BGABanner.Adapter() {
                   @Override
                   public void fillBannerItem(BGABanner banner, View view, Object model, int position) {
                       ((ImageView) view).setImageResource((int) model);
                   }
               });
               mBanner.setData(Arrays.asList(R.mipmap.a, R.mipmap.b, R.mipmap.c, R.mipmap.d, R.mipmap.e, R.mipmap.f,
                       R.mipmap.g, R.mipmap.h), null);
           }
       }

这里使用了一个开源轮播库 BGABanner 当作 Header, 该库的链接在此: BGAbanner

接着调用 Adapter 的 addHeader() 或者 addFooter()方法将该 Header 或 Footer 添加到 adapter 中:

    mAdapter.addHeader(new Header());

5.Configure 接口和 ConfigureAdapter 类

当默认的属性不能满足需求时, 可以自定义 layout 并设置为 PracticalRecyclerView 的属性:

   ...
   app:load_more_failed_layout="@layout/custom_load_more_failed_layout"  //当加载更多失败时显示的 View
   ...

若需要对该 View 进行设置, 就需要用到 Configure 接口, Configure 接口定义了以下方法,分别对属性中设置的 View 进行设置:

   public interface Configure {
       void configureEmptyView(View emptyView); //对 Empty View 进行设置

       void configureErrorView(View errorView); //对 Error View 进行设置

       void configureLoadingView(View loadingView); // 对 LoadingView 进行设置

       void configureLoadMoreView(View loadMoreView); // 对 LoadMore View 进行设置

       void configureNoMoreView(View noMoreView); //对 NoMore View 进行设置

       void configureLoadMoreErrorView(View loadMoreErrorView); // 对 LoadMoreError View 进行设置
   }

ConfigureAdapter 是对 Configure 接口的一个包装类, 可以选择实现其中的某一些方法,从而设置对应的 View:

    mRecycler.configureView(new ConfigureAdapter() {
               @Override
               public void configureLoadMoreFailedView(View loadMoreFailedView) {
                   super.configureLoadMoreFailedView(loadMoreFailedView);
                   loadMoreFailedView.setOnClickListener(new View.OnClickListener() {
                       @Override
                       public void onClick(View v) {
                           Toast.makeText(SingleItemActivity.this, "点击 LoadMoreFailedView 时应该进行的操作", Toast.LENGTH_SHORT).show();
                       }
                   });
               }

               @Override
               public void configureErrorView(View errorView) {
                   super.configureErrorView(errorView);
                   errorView.dosomething();
               }
           });

6.更多功能将会继续开发和完善

若您对此项目有一些自己的想法 , 欢迎来提 Pull Request.

关于我

若您对该项目有疑问,请联系我:

QQ:270362455

Gmail: ssseasonnn@gmail.com

License

Copyright 2016 Season.Zlc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Apps
About Me
Google+: Trinea trinea
GitHub: Trinea