zoukankan      html  css  js  c++  java
  • Android开发 封装向上拉动加载更多RecyclerView

    前言

      在很早以前在本人的博客 https://www.cnblogs.com/guanxinjing/p/10299889.html  提供了用RecyclerView实现上拉加载数据的思维,但是用这个方式实现后,每一个上拉加载页面几乎都需要重写大量重复代码。所以进行了重新的封装,以方便使用并且减少重复代码量。如果刚点击这个博客建议看看之前的博客,之前的博客实现思路比较,清晰讲解部分也比较多。

    封装后的RecyclerView

    使用时请注意,这里以内部类的形式封装了适配器,请使用这里封装的适配器配合一起使用。

    package net.wt.gate.ui.widget;
    
    import android.content.Context;
    import android.graphics.Color;
    import android.util.AttributeSet;
    import android.util.DisplayMetrics;
    import android.view.Gravity;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewConfiguration;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    import androidx.annotation.ColorInt;
    import androidx.annotation.IntDef;
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.annotation.StringRes;
    import androidx.recyclerview.widget.RecyclerView;
    
    import java.lang.annotation.Retention;
    import java.lang.annotation.Target;
    
    import static java.lang.annotation.ElementType.PARAMETER;
    import static java.lang.annotation.RetentionPolicy.SOURCE;
    
    
    public class UpLoadingRecyclerView extends RecyclerView {
        private boolean isScroll;
        private float downY;
        private int mHeightPixels;
        private OnUpScrollListener mOnUpScrollListener;
        private OnUpPullLoadListener mOnUpPullLoadListener;
    
        public UpLoadingRecyclerView(@NonNull Context context) {
            super(context);
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
            mHeightPixels = displayMetrics.heightPixels;
        }
    
        public UpLoadingRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
            mHeightPixels = displayMetrics.heightPixels;
        }
    
        public UpLoadingRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
            mHeightPixels = displayMetrics.heightPixels;
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            return super.dispatchTouchEvent(ev);
        }
    
        /**
         * 重写拦截的目的是只拦截移动事件,不拦截其他触摸事件
         *
         * @param e
         * @return
         */
        @Override
        public boolean onInterceptTouchEvent(MotionEvent e) {
            super.onInterceptTouchEvent(e);//一定要super.onInterceptTouchEvent(e);不要让RecyclerView的其他事件分发受到影响,否则会出现不滚动的问题
            switch (e.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    isScroll = false;//按下不拦截
                    downY = e.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (Math.abs(downY - e.getY()) >= ViewConfiguration.get(
                            getContext()).getScaledTouchSlop()) {//判断是否产生了最小滑动
                        isScroll = true;//移动了拦截触摸事件
                    } else {
                        isScroll = false;
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    isScroll = false;//松开不拦截
                    break;
            }
    
            return isScroll;
        }
    
    
        @Override
        public boolean onTouchEvent(MotionEvent e) {
            switch (e.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    return true;
                case MotionEvent.ACTION_MOVE:
                    break;
                case MotionEvent.ACTION_UP:
                    if (downY - e.getY() > mHeightPixels / 5) {//判断是不是从下往上滑动了屏幕的三分之一
                        if (mOnUpScrollListener != null) {
                            mOnUpScrollListener.onScroll();
                        }
                        if (getAdapter() != null && mOnUpPullLoadListener != null && getAdapter() instanceof Adapter) {
                            UpLoadingRecyclerView.Adapter adapter = (UpLoadingRecyclerView.Adapter) getAdapter();
                            if (adapter.isFooterPullUpLoading() && adapter.isFooterItemPosition()) {
                                mOnUpPullLoadListener.OnUpPullLoad();
                            }
                        }
    
                    }
                    break;
    
            }
            return super.onTouchEvent(e);
        }
    
        public void setOnUpScrollListener(OnUpScrollListener listener) {
            this.mOnUpScrollListener = listener;
    
        }
    
        public void setOnUpPullLoadListener(OnUpPullLoadListener onUpPullLoadListener) {
            this.mOnUpPullLoadListener = onUpPullLoadListener;
        }
    
        public interface OnUpScrollListener {
            void onScroll();
    
        }
    
        public interface OnUpPullLoadListener {
            void OnUpPullLoad();
        }
    
        public static abstract class Adapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter {
            private static final int FOOTER_VIEW = -101;
            private int currentFooterStatus = FooterStatus.FOOTER_NO_MORE_DATA;  //当前页角item状态
            private int scrollPosition;                                          //滚动位置
    
    
            public abstract RecyclerView.ViewHolder onCreateItemViewHolder(@NonNull ViewGroup parent, int viewType);
    
            public abstract RecyclerView.ViewHolder onCreateFooterViewHolder(@NonNull ViewGroup parent);
    
            public abstract void onBindItemViewHolder(@NonNull RecyclerView.ViewHolder holder, int position);
    
            public abstract void onBindFooterViewHolder(@NonNull RecyclerView.ViewHolder holder, @FooterStatus int currentFooterStatus);
    
            public abstract int getItemViewCount();
    
            @NonNull
            @Override
            public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                if (viewType != FOOTER_VIEW) {
                    return onCreateItemViewHolder(parent, viewType);
                }
                return onCreateFooterViewHolder(parent);
            }
    
    
            @Override
            public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
                scrollPosition = position;
                if (getItemViewType(position) != FOOTER_VIEW) {
                    onBindItemViewHolder(holder, position);
                    return;
                }
                onBindFooterViewHolder(holder, currentFooterStatus);
            }
    
    
            /**
             * 是否是最后位置
             *
             * @return
             */
            public boolean isFooterItemPosition() {
                return scrollPosition == getItemCount() - 1;
            }
    
            @Override
            public int getItemViewType(int position) {
                if (getItemCount() != 0 && position == getItemCount() - 1) {
                    return FOOTER_VIEW;
                }
                return super.getItemViewType(position);
            }
    
            @Override
            public int getItemCount() {
                return getItemViewCount() == 0 ? 0 : getItemViewCount() + 1;
            }
    
            /**
             * 修改页脚状态为加载中
             */
            public void setFooterLoading() {
                currentFooterStatus = FooterStatus.FOOTER_LOADING;
                notifyDataSetChanged();
            }
    
            /**
             * 修改页脚状态为网络异常
             */
            public void setFooterNetWorkError() {
                currentFooterStatus = FooterStatus.FOOTER_ERROR;
                notifyDataSetChanged();
            }
    
            /**
             * 修改页脚状态为没有更多数据
             */
            public void setFooterNoMoreData() {
                currentFooterStatus = FooterStatus.FOOTER_NO_MORE_DATA;
                notifyDataSetChanged();
            }
    
            /**
             * 修改页脚状态为上拉加载数据
             */
            public void setFooterPullUpLoading() {
                currentFooterStatus = FooterStatus.FOOTER_PULL_UP_LOADING;
                notifyDataSetChanged();
            }
    
            public boolean isFooterLoading() {
                return currentFooterStatus == FooterStatus.FOOTER_LOADING;
            }
    
            public boolean isFooterNetWorkError() {
                return currentFooterStatus == FooterStatus.FOOTER_ERROR;
            }
    
            public boolean isFooterNoMoreData() {
                return currentFooterStatus == FooterStatus.FOOTER_NO_MORE_DATA;
            }
    
            public boolean isFooterPullUpLoading() {
                return currentFooterStatus == FooterStatus.FOOTER_PULL_UP_LOADING;
            }
    
            /**
             * 创建使用简单页尾
             * @param parent
             * @param viewType
             * @param textSize
             * @param textColor
             * @return
             */
            public RecyclerView.ViewHolder createSimpleFooterView(@NonNull ViewGroup parent, int viewType, float textSize, @ColorInt int textColor) {
                if (viewType == Adapter.FOOTER_VIEW) {
                    TextView textView = new TextView(parent.getContext());
                    textView.setTextSize(dip2px(parent.getContext(), 14));
                    textView.setTextColor(Color.parseColor("#999999"));
                    textView.setGravity(Gravity.CENTER);
                    ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
                    layoutParams.height = dip2px(parent.getContext(), 30);
                    layoutParams.width = LayoutParams.MATCH_PARENT;
                    textView.setLayoutParams(layoutParams);
                    return new SimpleFooterViewHolder(textView);
    
                }
                return null;
            }
    
            /**
             * 绑定简单页尾的ViewHolder
             * @param holder
             * @param position
             * @param pullUpLoadingText
             * @param loadingText
             * @param errorText
             * @param notMoreDataText
             */
            public void bindSimpleFooterViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @StringRes int pullUpLoadingText, @StringRes int loadingText, @StringRes int errorText, @StringRes int notMoreDataText) {
                if (holder instanceof SimpleFooterViewHolder) {
                    switch (currentFooterStatus) {
                        case FooterStatus.FOOTER_PULL_UP_LOADING:
                            ((SimpleFooterViewHolder) holder).footerTextView.setText(pullUpLoadingText);
                            break;
                        case FooterStatus.FOOTER_LOADING:
                            ((SimpleFooterViewHolder) holder).footerTextView.setText(loadingText);
                            break;
                        case FooterStatus.FOOTER_ERROR:
                            ((SimpleFooterViewHolder) holder).footerTextView.setText(errorText);
                            break;
                        case FooterStatus.FOOTER_NO_MORE_DATA:
                            ((SimpleFooterViewHolder) holder).footerTextView.setText(notMoreDataText);
                            break;
                        default:
                            break;
                    }
                }
            }
    
            public static class SimpleFooterViewHolder extends RecyclerView.ViewHolder {
                TextView footerTextView;
    
                public SimpleFooterViewHolder(@NonNull View itemView) {
                    super(itemView);
                    footerTextView = (TextView) itemView;
                }
            }
    
        }
    
    
        @Retention(SOURCE)
        @Target({PARAMETER})
        @IntDef(value = {FooterStatus.FOOTER_PULL_UP_LOADING, FooterStatus.FOOTER_LOADING, FooterStatus.FOOTER_ERROR, FooterStatus.FOOTER_NO_MORE_DATA})
        public @interface FooterStatus {
            int FOOTER_PULL_UP_LOADING = 0;             //提示上拉加载更多
            int FOOTER_LOADING = 1;                     //加载中
            int FOOTER_ERROR = 2;                       //网络异常
            int FOOTER_NO_MORE_DATA = 3;                //没有更多内容
        }
    
        /**
         * 根据手机分辨率从DP转成PX
         *
         * @param context
         * @param dpValue
         * @return
         */
        private static int dip2px(Context context, float dpValue) {
            float scale = context.getResources().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }
    
    }
  • 相关阅读:
    迭代器实现斐波那契数列
    type 创建类,赋予类静态方法等
    使用types库修改函数
    使用property取代getter和setter方法
    pdb 进行调试
    nonlocal 访问变量
    timeit_list操作测试
    metaclass 拦截类的创建,并返回
    isinstance方法判断可迭代和迭代器
    苹果cms10 官方QQ微信防红防封代码
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/13204403.html
Copyright © 2011-2022 走看看