自定义的RecyclerView, 下拉刷新,加载更多.

编写用到的下拉刷新的布局文件

<?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="wrap_content"
              android:background="#f00"
              android:gravity="center"
              android:orientation="vertical"
    >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/ll"
        >
        <TextView
            android:id="@+id/status"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="显示一些东西"
            android:textColor="#000"
            />
    </LinearLayout>
</LinearLayout>

自定义RecyclerView 封装了下拉刷新和加载更多的功能


/**
 * 下拉刷新和加载更多的 自定View
 * Created by SwmIsMe on 2017/3/2.
 */
public class MyRecyclerView extends RecyclerView {

    public final static int STATE_NORMAL = 0;
    public final static int STATE_READY = 1;
    public final static int STATE_REFRESHING = 2;

    MyLoadRefreshAdapter mLoadRefreshAdapter;
    View headerView, footerView;

    private int mState = STATE_NORMAL;
    //    头布局的高度
    int headerViewHeight;
    //    是否正在触摸
    boolean isOnTouching;
    TextView status;
    boolean isRefresh;
    private LinearLayout mLl;
    private LinearLayout.LayoutParams mParams;
    private LayoutManager mLayoutManager;

    public MyRecyclerViewListener getMyRecyclerViewListener() {
        return myRecyclerViewListener;
    }

    //    设置 监听
    public void setMyRecyclerViewListener(MyRecyclerViewListener myRecyclerViewListener) {
        this.myRecyclerViewListener = myRecyclerViewListener;
    }

    MyRecyclerViewListener myRecyclerViewListener;

    public MyRecyclerView(Context context) {
        super(context);
    }

    public MyRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    int lastX, lastY;

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        int x = (int) e.getX();
        int y = (int) e.getY();

        switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                isOnTouching = true;
//                获取到 轮播的view
                View view1 = this.getChildAt(1);
//                获取到  轮播的view安排的位置.
                int loopViewPagerPosition = this.getChildLayoutPosition(view1);
//                如果 轮播的view安排(layout)的位置. 是第一个 触发下拉刷新的操作.
                if (loopViewPagerPosition == 1) {
                    if (lastY == 0) {
                        lastY = y;
                    }
                    int dy = lastY - y;
                    int dx = lastX - x;
                    int yabs = Math.abs(dy);
                    int xabs = Math.abs(dx);
                    if (yabs > xabs) {
                        isRefresh = true;
                        changeHeight(dy);
                        this.requestDisallowInterceptTouchEvent(true);
                    } else {
                        this.requestDisallowInterceptTouchEvent(false);
                    }
                    lastX = x;
                    lastY = y;
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                isRefresh = false;
                isOnTouching = false;
//                归零
                lastY = 0;
//                开始刷新
                if (mState == STATE_READY || mState == STATE_REFRESHING) {
                    onStatusChange(STATE_REFRESHING);
                    autoSize(0);
                }
//                回归到 隐藏的位置
                if (mState == STATE_NORMAL) {
                    autoSize(-headerViewHeight);
                }
                break;
        }
        return super.onTouchEvent(e);
    }

    //    通过改变 topMargin的值.改变高度
    private void changeHeight(int dy) {
        mParams.topMargin -= dy;
        int margin = mParams.topMargin;
        mLl.setLayoutParams(mParams);
        setStateByHeight(margin, false);
    }

    /**
     * 更新 头布局的高度
     *
     * @param targetHeight 要改变到的高度  当这个高度为0时,topMargin为0,显示整个刷新的界面,
     *                     -headerViewHeight  隐藏头布局
     */
    public void autoSize(int targetHeight) {
        int currentHeight = mParams.topMargin;
//        从当前高度 到 目前高度,的动画变化值.
        ValueAnimator objectAnimator = ValueAnimator.ofInt(currentHeight, targetHeight);
//        设置下拉刷新的高度
        objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int animatedValue = (int) animation.getAnimatedValue();
//                根据高度设置文本
                setStateByHeight(animatedValue, true);
                mParams.topMargin = animatedValue;
                mLl.setLayoutParams(mParams);
            }
        });
        objectAnimator.start();
    }


    //    设置加载更多的判断
    @Override
    public void setLayoutManager(final LayoutManager layout) {
        super.setLayoutManager(layout);

        this.addOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
            }


            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (isRefresh) {
                    return;
                }
                if (mState != STATE_NORMAL) {
                    return;
                }
                LogUtils.e("new state" + newState);
                //判断是否最后一item个显示出来
                mLayoutManager = getLayoutManager();
                //可见的item个数
                int visibleChildCount = mLayoutManager.getChildCount();
//                如果大于0 并且 状态不等于空闲 并且 没有在加载更多
                if (visibleChildCount > 0 && newState == RecyclerView.SCROLL_STATE_IDLE && !isLoadMore) {
//                    获取最后一个 view 除加载更多view
                    View lastVisibleView = recyclerView.getChildAt(recyclerView.getChildCount() - 1);
//                    返回给定子视图的适配器位置
                    int lastVisiblePosition = recyclerView.getChildLayoutPosition(lastVisibleView);
//                    如果 最后一个可见的位置 大于等于
                    if (lastVisiblePosition >= mLayoutManager.getItemCount() - 1) {
//                        加载更多view 可见
                        footerView.setVisibility(VISIBLE);
                        isLoadMore = true;
//                        加载更多
                        if (myRecyclerViewListener != null) {
                            myRecyclerViewListener.onLoadMore();
                        }
                    } else {
                        footerView.setVisibility(GONE);
                    }
                }

            }
        });
    }

    //    根据高度来设置 现在的状态
    private void setStateByHeight(int height, boolean isAuto) {
        if (mState == STATE_REFRESHING) {
            return;
        }
//        如果 当前的高度 小于 头布局的高度
        if (height < headerViewHeight) {
            onStatusChange(STATE_NORMAL);
        } else if (height > headerViewHeight) {
            onStatusChange(STATE_READY);
        } else if (height == headerViewHeight && !isOnTouching && !isAuto) {
            onStatusChange(STATE_REFRESHING);
        }
    }

    boolean isLoadMore;

    public void onStatusChange(int status) {
        mState = status;
        switch (status) {
            case STATE_READY:
                this.status.setText("松开刷新...");
                break;
            case STATE_NORMAL:
                this.status.setText("下拉刷新...");
                break;
            case STATE_REFRESHING:
                this.status.setText("正在刷新...");
                if (myRecyclerViewListener != null) {
                    myRecyclerViewListener.onRefresh();
                }
                break;
        }
    }

    //    初始化头尾布局 和 头尾view的适配器
    @Override
    public void setAdapter(Adapter adapter) {
        ArrayList<View> headers = new ArrayList<>();
        ArrayList<View> footers = new ArrayList<>();
//        加载下拉刷新的布局文件
        View refreshView = LayoutInflater.from(getContext()).inflate(R.layout.item_recycler_refresh, null);
        headerView = refreshView;
        status = (TextView) refreshView.findViewById(R.id.status);
        mLl = (LinearLayout) refreshView.findViewById(R.id.ll);
        headerView.post(new Runnable() {
            @Override
            public void run() {
//                头布局真正的高度
                headerViewHeight = headerView.getHeight();
//                设置layout参数  隐藏头布局
                mParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                mParams.topMargin = -headerViewHeight;
                mParams.width = ScreenUtils.screenW;
                mLl.setLayoutParams(mParams);
            }
        });
//        将头布局添加到 集合中
        headers.add(headerView);

//        初始化 尾布局
        LinearLayout footerLayout = new LinearLayout(getContext());
        footerLayout.setGravity(Gravity.CENTER);
        footerLayout.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        footers.add(footerLayout);
        footerLayout.setPadding(0, 15, 0, 15);
        footerLayout.addView(new ProgressBar(getContext(), null, android.R.attr.progressBarStyleSmall));

        TextView text = new TextView(getContext());
        text.setText("正在加载...");
        footerLayout.addView(text);
        footerView = footerLayout;
        footerView.setVisibility(GONE);

//        初始化 适配器
        mLoadRefreshAdapter = new MyLoadRefreshAdapter(adapter, headers, footers);
        super.setAdapter(mLoadRefreshAdapter);
    }

    public interface MyRecyclerViewListener {
        void onRefresh();

        void onLoadMore();
    }

    //    完成加载更多
    public void setLoadMoreComplete() {
//        直接隐藏 尾布局
        footerView.setVisibility(GONE);
        isLoadMore = false;
    }

    //    完成下拉刷新
    public void setRefreshComplete() {
        onStatusChange(STATE_NORMAL);
        autoSize(-headerViewHeight);
    }

}

自定义 MyLoadRefreshAdapter 适配器

/**
 * 实现显示头部和尾部item的adapter,把头部尾部的事情交给这个adapter来做,其他的交给子adapter
 * Created by SwmIsMe on 2017/3/2.
 */
public class MyLoadRefreshAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    public ArrayList<View> headerViews = new ArrayList<>();
    public ArrayList<View> footViews = new ArrayList<>();
    public RecyclerView.Adapter adapter;

    public MyLoadRefreshAdapter(RecyclerView.Adapter adapter, ArrayList<View> headerViews, ArrayList footViews) {
        this.adapter = adapter;
        this.headerViews = headerViews;
        this.footViews = footViews;
    }

    MyLoadRefreshListener mLoadRefreshListener;

    public MyLoadRefreshListener getLoadRefreshListener() {
        return mLoadRefreshListener;
    }

    public void setLoadRefreshListener(MyLoadRefreshListener loadRefreshListener) {
        mLoadRefreshListener = loadRefreshListener;
    }

    public interface MyLoadRefreshListener {
        //        获取现在item的类型
        void getNowItemType(int itemPosition);
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == RecyclerView.INVALID_TYPE) {
            //头部item
            return new RecyclerView.ViewHolder(headerViews.get(0)) {
            };
        } else if (viewType == (RecyclerView.INVALID_TYPE - 1)) {
            //尾部item
            return new RecyclerView.ViewHolder(footViews.get(0)) {
            };
        }
        return adapter.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (position >= 0 && position < headerViews.size()) {
            return;
        }

//        交给 其他的适配器处理
        if (adapter != null) {
            int p = position - headerViews.size();
            if (p < adapter.getItemCount()) {
                adapter.onBindViewHolder(holder, p);
            }
        }
    }


    @Override
    public int getItemViewType(int position) {
        if (position >= 0 && position < headerViews.size()) {
            //如果是头部则返回一个不可用的标识,表示这是头部item
            return RecyclerView.INVALID_TYPE;
        }

        if (adapter != null) {
            int p = position - headerViews.size();
            if (p < adapter.getItemCount()) {
                return adapter.getItemViewType(p);
            }
        }

        return RecyclerView.INVALID_TYPE - 1;//默认返回表示是尾部的item
    }

    @Override
    public int getItemCount() {
        return getCount();
    }

    public int getCount() {
        int count = headerViews.size() + footViews.size();
        if (adapter != null) {
            count += adapter.getItemCount();
        }
        return count;
    }

}

使用,添加监听

 mHomeRecyclerview.setLayoutManager(new LinearLayoutManager(getContext()));
        MyHomeRecyclerviewAdapter adapter = new MyHomeRecyclerviewAdapter(LayoutInflater.from(getContext()));
        mHomeRecyclerview.setAdapter(adapter);

//        设置 下拉刷新 和加载更多的 监听
        mHomeRecyclerview.setMyRecyclerViewListener(new MyRecyclerView.MyRecyclerViewListener() {
            @Override
            public void onRefresh() {
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtils.showToast("onRefresh");
                        mHomeRecyclerview.setRefreshComplete();
                    }
                }, 2000);
            }

            @Override
            public void onLoadMore() {
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        ToastUtils.showToast("onLoadMore");
                        mHomeRecyclerview.setLoadMoreComplete();
                    }
                }, 2000);

            }
        });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的示例代码: 首先,在XML布局文件中添加一个RecyclerView和SwipeRefreshLayout控件: ```xml <androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipe_refresh_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> ``` 然后,在Activity或Fragment中初始化RecyclerView和SwipeRefreshLayout,并设置相应的监听器: ```java // 初始化RecyclerView和SwipeRefreshLayout mRecyclerView = findViewById(R.id.recycler_view); mSwipeRefreshLayout = findViewById(R.id.swipe_refresh_layout); // 设置布局管理器和适配器 mLayoutManager = new LinearLayoutManager(this); mAdapter = new MyAdapter(mDataList); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setAdapter(mAdapter); // 设置下拉刷新监听器 mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { // 进行下拉刷新操作 refreshData(); } }); // 设置上拉加载多监听器 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if (newState == RecyclerView.SCROLL_STATE_IDLE && isSlideToBottom(recyclerView)) { // 滑动到底部,触发加载多操作 loadMoreData(); } } }); // 判断RecyclerView是否滑动到底部 private boolean isSlideToBottom(RecyclerView recyclerView) { LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition(); int itemCount = layoutManager.getItemCount(); return lastVisibleItemPosition == (itemCount - 1); } // 进行下拉刷新操作 private void refreshData() { // 在这里进行刷新数据的操作 // 刷新完成后调用mSwipeRefreshLayout.setRefreshing(false)停止刷新动画 } // 进行上拉加载多操作 private void loadMoreData() { // 在这里进行加载多数据的操作 // 加载完成后调用mAdapter.notifyDataSetChanged()新列表 } ``` 需要注意的是,上述代码中的MyAdapter是自定义RecyclerView适配器,需要根据实际情况进行修改。另外,刷新和加载多操作需要在子线程中进行,可以使用AsyncTask等方式进行异步处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值