android RecycleView实现下拉刷新和上拉加载

android 的下拉刷新,上拉加载功能,翻页时显示从第1页开始到当前页面的内容,并且当前显示的是当前页的内容;

1. PullRefreshRecyclerView.java : 翻页控件

public class PullRefreshRecyclerView extends LinearLayout implements SwipeRefreshLayout.OnRefreshListener, View.OnTouchListener {
  private SwipeRefreshLayout swipeRefreshLayout;
  private RecyclerView recyclerView;
  private LinearLayout footerView;
  private OnPullRefreshListener listener;
  //是否正在刷新
  private boolean isRefreshing = false;
  //是否正在加载
  private boolean isLoading = false;

  //是否有更多数据
  private boolean hasMore = false;

  public PullRefreshRecyclerView(Context context) {
    this(context, null);
  }

  public PullRefreshRecyclerView(Context context, AttributeSet attrs) {
    super(context, attrs);
    initView(context);
    initListener();
    init();
  }

  private void initView(Context context) {
    LayoutInflater.from(context).inflate(R.layout.pull_recycler_layout, this, true);
    swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);
    recyclerView = findViewById(R.id.recyclerView);
    footerView = findViewById(R.id.footerView);

  }

  private void initListener() {
    swipeRefreshLayout.setOnRefreshListener(this);
    recyclerView.addOnScrollListener(new PullableScroll());
    //防止滚动的时候,滑动View
    recyclerView.setOnTouchListener(this);
  }

  private void init() {
    swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_green_dark,
        android.R.color.holo_blue_dark,
        android.R.color.holo_orange_dark);
    //隐藏垂直滚动条
    recyclerView.setVerticalScrollBarEnabled(true);
    //item高度固定时,设置该选项提高性能
    recyclerView.setHasFixedSize(true);
    //设置item动画效果
    recyclerView.setItemAnimator(new DefaultItemAnimator());
  }

  public void setHasFixedSize(boolean hasFixedSize) {
    recyclerView.setHasFixedSize(hasFixedSize);
  }

  public void setItemAnimator(RecyclerView.ItemAnimator animator) {
    recyclerView.setItemAnimator(animator);
  }

  public void setLayoutManager(RecyclerView.LayoutManager layout) {
    recyclerView.setLayoutManager(layout);
  }

  public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
    recyclerView.setVerticalScrollBarEnabled(verticalScrollBarEnabled);
  }

  public void addItemDecoration(RecyclerView.ItemDecoration decor) {
    recyclerView.addItemDecoration(decor);

  }

  public void setAdapter(RecyclerView.Adapter adapter) {
    recyclerView.setAdapter(adapter);
  }

  /**
   * 设置监听下拉或上拉的事件
   *
   * @param listener
   */
  public void setOnPullRefreshListener(OnPullRefreshListener listener) {
    this.listener = listener;
  }

  /**
   * 设置是否有更多数据
   *
   * @param hasMore
   */
  public void setHasMore(boolean hasMore) {
    this.hasMore = hasMore;
  }

  /**
   * 滚动到顶部
   */
  public void scrollToTop() {
    recyclerView.scrollToPosition(0);
  }

  /**
   * 正在刷新
   */
  @Override
  public void onRefresh() {
    isRefreshing = true;
    if (listener != null) {
      listener.onRefresh();
    }

  }

  /**
   * 设置是否允许下拉
   *
   * @param enable
   */
  public void setRefreshEnable(boolean enable) {
    swipeRefreshLayout.setEnabled(enable);
  }

  /**
   * 滚动时判断能否能刷新
   *
   * @return
   */
  private boolean isRefreshEnable() {
    return !isRefreshing && !isLoading;
  }

  /**
   * 正在加载更多
   */
  public void doLoadMore() {
    if (!isLoading && hasMore && !isRefreshing) {
      footerView.setVisibility(View.VISIBLE);
      isLoading = true;
      //禁止下拉
      setRefreshEnable(false);
      if (listener != null) {
        listener.onLoadMore();
      }
    }
  }

  /**
   * 刷新或加载完成
   */
  public void refreshOrLoadComplete() {
    isRefreshing = false;
    swipeRefreshLayout.setRefreshing(false);
    isLoading = false;
    footerView.setVisibility(View.GONE);
    //允许下拉
    this.setEnabled(true);
  }

  @Override
  public boolean onTouch(View v, MotionEvent event) {
    return isRefreshing || isLoading;
  }

  public interface OnPullRefreshListener {
    /**
     * 刷新操作
     */
    void onRefresh();

    /**
     * 加载操作
     */
    void onLoadMore();
  }

  /**
   * 监听RecycleView滑动底部或顶部
   */
  class PullableScroll extends RecyclerView.OnScrollListener {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
      super.onScrolled(recyclerView, dx, dy);
      int lastVisibleItem = 0;
      int firstVisibleItem = 0;
      RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
      int totalItemCount = layoutManager.getItemCount();
      if (layoutManager instanceof LinearLayoutManager) {
        LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
        lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
        firstVisibleItem = linearLayoutManager.findFirstCompletelyVisibleItemPosition();
      } else if (layoutManager instanceof StaggeredGridLayoutManager) {
        StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
        // since may lead to the final item has more than one StaggeredGridLayoutManager the particularity of the so here that is an array
        // this array into an array of position and then take the maximum value that is the last show the position value
        int[] lastPositions = new int[((StaggeredGridLayoutManager) layoutManager).getSpanCount()];
        staggeredGridLayoutManager.findLastVisibleItemPositions(lastPositions);
        lastVisibleItem = findMax(lastPositions);
        firstVisibleItem = staggeredGridLayoutManager.findFirstVisibleItemPositions(lastPositions)[0];
      }

      pullRefreshEnable(firstVisibleItem, totalItemCount);
      if (isSlideToBottom(recyclerView)) {
        loadMore(dx, dy, lastVisibleItem, totalItemCount);
      }

    }

    private int findMax(int[] lastPositions) {
      int max = lastPositions[0];
      for (int value : lastPositions) {
        if (value > max) {
          max = value;
        }
      }
      return max;
    }
  }

  /**
   * 判断是否滑动到底部
   *
   * @param recyclerView
   * @return
   */
  public boolean isSlideToBottom(RecyclerView recyclerView) {
    if (recyclerView == null) {
      return false;
    }
    if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset()
        >= recyclerView.computeVerticalScrollRange()) {
      return true;
    }
    return false;
  }

  private void loadMore(int dx, int dy, int lastVisibleItem, int totalItemCount) {
    //滚动到底部时且有更多数据能够上拉加载
    if (lastVisibleItem >= totalItemCount - 1 && (dx > 0 || dy > 0)) {
      doLoadMore();
    }
  }

  private void pullRefreshEnable(int firstVisibleItem, int totalItemCount) {
    //滚动到顶部时能够下拉刷新
    if (firstVisibleItem == 0 || totalItemCount == 0) {
      if (isRefreshEnable()) {
        //允许下拉
        setRefreshEnable(true);
      }
    } else {
      //禁止下拉
      setRefreshEnable(false);
    }
  }

}

2. PunishListActivity.java: 调用

@Route(path = Page.ACTIVITY_PUNISH_LIST)
public class PunishListActivity extends BaseActivity implements View.OnClickListener, PullRefreshRecyclerView.OnPullRefreshListener {
  private static final String TAG = "PunishListActivity";
  private List<PunishBean> punishBeans = new ArrayList<>();
  private Context mContext;
  private EditText et_punish_searchName;
  private ImageView iv_search;
  private PullRefreshRecyclerView prr_punish;
  private String officeName = "";
  private int pageNo = 1;
  private boolean isLastPage = false;
  private PunishAdapter punishAdapter;

  @Override
  public void onBeforeSetContentView() {
    StatusBarUtil.translucent(this, ContextCompat.getColor(this, R.color.color_0a5fb6));
  }

  @Override
  public int getLayoutResID() {
    return R.layout.activity_punish_list;
  }

  @Override
  protected CharSequence setActionBarTitle() {
    return "行政处罚";
  }
  @Nullable
  @Override
  public AppBarConfig getAppBarConfig() {
    return mAppBarCompat;
  }

  @Override
  public int setActionBarRightVisibility() {
    return View.VISIBLE;
  }

  @Override
  public CharSequence setActionBarRightText() {
    return "添加";
  }

  public void onResume(){
    super.onResume();
    getPunishList("");
  }

  @Override
  public void initContentView(@Nullable Bundle savedInstanceState) {
    mContext = PunishListActivity.this;
    et_punish_searchName = findViewById(R.id.et_punish_searchName);
    iv_search = findViewById(R.id.iv_search);
    iv_search.setOnClickListener(this);
    prr_punish = findViewById(R.id.prr_punish);
    prr_punish.setOnPullRefreshListener(this);
    prr_punish.setHasMore(true);
  }

  @Override
  public void initData(@Nullable Bundle savedInstanceState) {
    punishAdapter = new PunishAdapter(mContext,punishBeans);
    LinearLayoutManager manager = new LinearLayoutManager(mContext);
    manager.setOrientation(RecyclerView.VERTICAL);
    prr_punish.setLayoutManager(manager);
    prr_punish.setAdapter(punishAdapter);
//    getPunishList();
  }

  private void getPunishList(String officeName){
    HashMap<String, Object> baseParam = WebFrontUtil.getBaseParam();
    baseParam.put("pageNo", pageNo);
    baseParam.put("pageSize", 10);

    baseParam.put("officeName", officeName);
    OkHttpUtil.post(TAG, WebApi.PUNISH_LIST_URL, baseParam, new StringCallback() {
      @Override
      public void onError(Call call, Exception e, int id) {
        hideWaitDialog();
        Log.d(TAG,""+e);
      }

      @Override
      public void onResponse(String response, int id) {
        Log.d(TAG,"response==="+response);
        try {
          JSONObject object = new JSONObject(response);
          hideWaitDialog();
          if ((int)object.get("code") == 200) {
            JSONObject object1 = object.getJSONObject("data");
            PunishBeanList punishBeanList = new Gson().fromJson(object1.toString(),PunishBeanList.class);
            Log.d(TAG,"response==="+punishBeanList.getList().size());
            if (pageNo == 1) {
              punishBeans.clear();
            }
            if (punishBeanList.getList() != null && punishBeanList.getList().size() != 0) {
              List<PunishBean> addPunishs = new ArrayList<>();
              addPunishs = punishBeanList.getList();
              if (punishBeans.size() > 0) {
                punishBeans.addAll(addPunishs);
                punishAdapter.addMoreData(addPunishs);
              } else {
                punishBeans = addPunishs;
                punishAdapter.setData(addPunishs);
              }

              if (punishBeanList.isLastPage()) {
                isLastPage = true;
                Log.e(TAG,"isLastPage = true ");
              }else {
                isLastPage = false;
                Log.e(TAG,"isLastPage = false ");
              }
            }
          } else {
            Toast.makeText(mContext,object.get("message").toString(),Toast.LENGTH_SHORT).show();
          }
        } catch (JSONException e) {
          e.printStackTrace();
        }
      }
    });
  }

  @Override
  protected void actionBarRightOnClick() {
    ARouter.getInstance().build(Page.ACTIVITY_PUNISH_ADD).navigation();
  }

  @Override
  public void onClick(View view) {
    switch (view.getId()) {
      case R.id.iv_search:
        showWaitDialog();
        officeName = et_punish_searchName.getText().toString();
        pageNo = 1;
        isLastPage = false;
        getPunishList(officeName);
        break;
    }
  }

  @Override
  public void onRefresh() {
    prr_punish.refreshOrLoadComplete();
    pageNo = 1;
    getPunishList(officeName);
    prr_punish.setRefreshEnable(true);
  }

  @Override
  public void onLoadMore() {
    Log.d(TAG,"onLoadMore===================");
    prr_punish.refreshOrLoadComplete();
    if (isLastPage) {
      prr_punish.setRefreshEnable(false);
    } else {
      pageNo += 1;
      getPunishList(officeName);
    }
  }
}

3. PunishAdapter.java

public class PunishAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
  private Context mContext;
  private List<PunishBean> punishList;

  public PunishAdapter(Context mContext, List<PunishBean> punishList) {
    this.mContext = mContext;
    this.punishList = punishList;
  }

  @NonNull
  @Override
  public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.punish_item,parent,false);
    PunishHolder punishHolder = new PunishHolder(view);
    return punishHolder;
  }

  @Override
  public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
    PunishBean punishBean = punishList.get(position);
    PunishHolder punishHolder = (PunishHolder) holder;
    punishHolder.tv_punishName.setText(punishBean.getOfficeName());
    punishHolder.tv_faren.setText(punishBean.getLegalPerson());
    punishHolder.tv_punishMode.setText(punishBean.getPunishWay());
    punishHolder.tv_punishReason.setText(punishBean.getReason());
    punishHolder.tv_punishTime.setText(punishBean.getUpdateTime());
    punishHolder.tv_punishDesc.setText(punishBean.getRemarks());
    punishHolder.itemView.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        Bundle bundle = new Bundle();
        bundle.putSerializable("punishDetail",punishBean);
        ARouter.getInstance().build(Page.ACTIVITY_PUNISH_DETAIL).with(bundle).navigation();
      }
    });
  }

  /*
  * 向列表尾部添加数据
  * */
  public void addMoreData(List<PunishBean> list) {
    int oldSize = punishList.size();
    if (list != null && list.size() > 0) {
      punishList.addAll(punishList.size(), list);
      notifyItemRangeInserted(oldSize, list.size());
    }
  }

  /*
   * 填充新数据
   * */
  public void setData(List<PunishBean> data) {
    if (data != null && data.size() > 0) {
      punishList.clear();
      punishList.addAll(data);
      notifyDataSetChanged();
    }
  }

  @Override
  public int getItemCount() {
    return punishList==null? 0:punishList.size();
  }

  class PunishHolder extends RecyclerView.ViewHolder {
    private TextView tv_punishName,tv_faren,tv_punishMode,tv_punishReason,tv_punishTime,tv_punishDesc;

    public PunishHolder(@NonNull View itemView) {
      super(itemView);
      tv_punishName = itemView.findViewById(R.id.tv_punishName);
      tv_faren = itemView.findViewById(R.id.tv_faren);
      tv_punishMode = itemView.findViewById(R.id.tv_punishMode);
      tv_punishReason = itemView.findViewById(R.id.tv_punishReason);
      tv_punishTime = itemView.findViewById(R.id.tv_punishTime);
      tv_punishDesc = itemView.findViewById(R.id.tv_punishDesc);

    }
  }
}

4. 布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:fitsSystemWindows="true"
  android:orientation="vertical"
  android:layout_margin="@dimen/px40"
  android:background="@color/color_ffffff"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:context=".modules.punish.PunishListActivity">
  <RelativeLayout
    android:id="@+id/rl_punish_search"
    android:layout_width="match_parent"
    android:layout_marginTop="@dimen/px20"
    android:layout_height="103px"
    android:background="@drawable/bg_radius_blue">

    <EditText
      android:id="@+id/et_punish_searchName"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_marginStart="@dimen/px44"
      android:layout_marginEnd="@dimen/px110"
      android:background="@null"
      android:hint="请输入单位名称"
      android:inputType="text"
      android:textColor="@color/color_hint"
      android:textColorHint="@color/color_hint"
      android:textSize="@dimen/font_14" />

    <ImageView
      android:id="@+id/iv_search"
      android:layout_width="@dimen/px54"
      android:layout_height="@dimen/px54"
      android:layout_alignParentEnd="true"
      android:layout_centerVertical="true"
      android:layout_marginEnd="@dimen/px50"
      android:src="@drawable/icon_text_search" />
  </RelativeLayout>
  <com.nmpa.nmpaapp.widget.PullRefreshRecyclerView
    android:id="@+id/prr_punish"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
</LinearLayout>

本文已经被整理到《Android下拉刷新上拉加载效果》,欢迎大家学习研究。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android官方下拉刷新控件SwipeRefreshLayout使用详解

    可能开发安卓的人大多数都用过很多下拉刷新的开源组件,但是今天用了官方v4支持包的SwipeRefreshLayout觉得效果也蛮不错的,特拿出来分享. 简介: SwipeRefreshLayout组件只接受一个子组件:即需要刷新的那个组件.它使用一个侦听机制来通知拥有该组件的监听器有刷新事件发生,换句话说我们的Activity必须实现通知的接口.该Activity负责处理事件刷新和刷新相应的视图.一旦监听者接收到该事件,就决定了刷新过程中应处理的地方.如果要展示一个"刷新动画",它必须

  • Android RecyclerView实现下拉刷新和上拉加载

    RecyclerView已经出来很久了,许许多多的项目都开始从ListView转战RecyclerView,那么,上拉加载和下拉刷新是一件很有必要的事情. 在ListView上,我们可以通过自己添加addHeadView和addFootView去添加头布局和底部局实现自定义的上拉和下拉,或者使用一些第三方库来简单的集成,例如Android-pulltorefresh或者android-Ultra-Pull-to-Refresh,后者的自定义更强,但需要自己实现上拉加载. 而在下面我们将用两种方式

  • Android中使用RecyclerView实现下拉刷新和上拉加载

    推荐阅读:使用RecyclerView添加Header和Footer的方法                       RecyclerView的使用之HelloWorld RecyclerView 是Android L版本中新添加的一个用来取代ListView的SDK,它的灵活性与可替代性比listview更好.本文给大家介绍如何为RecyclerView添加下拉刷新和上拉加载,过去在ListView当中添加下拉刷新和上拉加载是非常方便的利用addHeaderView和addFooterVie

  • Android RecyclerView 上拉加载更多及下拉刷新功能的实现方法

    RecyclerView 已经出来很久了,但是在项目中之前都使用的是ListView,最近新的项目上了都大量的使用了RecycleView.尤其是瀑布流的下拉刷新,网上吧啦吧啦没有合适的自己总结了一哈. 先贴图上来看看: 使用RecyclerView实现上拉加载更多和下拉刷新的功能我自己有两种方式: 1.使用系统自带的Android.support.v4.widget.SwipeRefreshLayout这个控价来实现. 2.自定义的里面带有RecyleView的控件. 使用RecycleVie

  • Android实现上拉加载更多以及下拉刷新功能(ListView)

    首先为大家介绍Andorid5.0原生下拉刷新简单实现. 先上效果图: 相对于上一个19.1.0版本中的横条效果好看了很多.使用起来也很简单. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" and

  • Android下拉刷新ListView——RTPullListView(demo)

    下拉刷新在越来越多的App中使用,已经形成一种默认的用户习惯,遇到列表显示的内容时,用户已经开始习惯性的拉拉.在交互习惯上已经形成定性.之前在我的文章<IOS学习笔记34-EGOTableViewPullRefresh实现下拉刷新>中介绍过如何在IOS上实现下拉刷新的功能.今天主要介绍下在Android上实现下拉刷新的Demo,下拉控件参考自Github上开源项目PullToRefresh,并做简单修改.最终效果如下:                         工程结构如下: 使用过程中

  • Android下拉刷新完全解析,教你如何一分钟实现下拉刷新功能(附源码)

    最近项目中需要用到ListView下拉刷新的功能,一开始想图省事,在网上直接找一个现成的,可是尝试了网上多个版本的下拉刷新之后发现效果都不怎么理想.有些是因为功能不完整或有Bug,有些是因为使用起来太复杂,十全十美的还真没找到.因此我也是放弃了在网上找现成代码的想法,自己花功夫编写了一种非常简单的下拉刷新实现方案,现在拿出来和大家分享一下.相信在阅读完本篇文章之后,大家都可以在自己的项目中一分钟引入下拉刷新功能. 首先讲一下实现原理.这里我们将采取的方案是使用组合View的方式,先自定义一个布局

  • Android下拉刷新上拉加载控件(适用于所有View)

    前面写过一篇关于下拉刷新控件的文章下拉刷新控件终结者:PullToRefreshLayout,后来看到好多人还有上拉加载更多的需求,于是就在前面下拉刷新控件的基础上进行了改进,加了上拉加载的功能.不仅如此,我已经把它改成了对所有View都通用!可以随心所欲使用这两个功能~~ 我做了一个大集合的demo,实现了ListView.GridView.ExpandableListView.ScrollView.WebView.ImageView.TextView的下拉刷新和上拉加载.后面会提供demo的

  • Android RecyclerView添加上拉加载更多效果

    先看一下效果 刷新的时候是这样的: 没有更多的时候是这样的: 既然有刷新的时候有两种状态就要定义两个状态 //普通布局的type static final int TYPE_ITEM = 0; //脚布局 static final int TYPE_FOOTER = 1; 在特定的时候去显示: @Override public int getItemViewType(int position) { //如果position加1正好等于所有item的总和,说明是最后一个item,将它设置为脚布局

  • Android使用recyclerview打造真正的下拉刷新上拉加载效果

    前言 前段时间需要用到recyclerview,就想找个封装好的下拉刷新,上拉加载的库,结果愣是没找到,便自己写了一个. 注意:我说的是"上拉加载",不是滑到底部自动加载. 虽然现在自动加载是主流和趋势,但也不排除有时候就需要用到上拉加载啊,毕竟林子大了,什么样的产品经理都有对吧. 代码写好后,准备发布到bintray的时候,向同事征求这个项目的名字,同事说:"就叫DZTRecyclerview!" 不解,同事解释:"叼炸天Recyclerview!&qu

  • Android PullToRefreshLayout下拉刷新控件的终结者

    说到下拉刷新控件,网上版本有很多,很多软件也都有下拉刷新功能.有一个叫XListView的,我看别人用过,没看过是咋实现的,看这名字估计是继承自ListView修改的,不过效果看起来挺丑的,也没什么扩展性,太单调了.看了QQ2014的列表下拉刷新,发现挺好看的,我喜欢,贴一下图看一下qq的下拉刷新效果: 不错吧?嗯,是的.一看就知道实现方式不一样.咱们今天就来实现一个下拉刷新控件.由于有时候不仅仅是ListView需要下拉刷新,ExpandableListView和GridView也有这个需求,

随机推荐