android RecycleView下拉刷新,上拉加载

本文介绍了一个自定义的PullRefreshRecyclerView组件,用于实现Android应用中的下拉刷新和上拉加载功能。该组件集成了SwipeRefreshLayout和RecyclerView,支持动态加载数据,同时提供了丰富的配置选项,如设置刷新动画、滚动条显示等。

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>

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值