美文网首页
SwipeRefreshLayout+RecyclerView实

SwipeRefreshLayout+RecyclerView实

作者: 古早味蛋糕 | 来源:发表于2023-01-06 17:54 被阅读0次
    一、介简

    上一节写自定义RecyclerView实现了一个简单的下拉刷新与加载更多,这一节主要写外包RecyclerView方式实现的下拉刷新与加载更多,网上相关的内容有很多,不过内容太多不够简洁。所以想写一个以SwipeRefreshLayout外包SwipeRefreshLayout的实现简洁方式,不搞复杂化,主要以能快速看懂看会为主。

    二、SwipeRefreshLayout
    1、SwipeRefreshLayout是google官方推荐使用的下拉刷新的控件,如果用户想通过垂直滑动手势刷新视图的内容,就可以使用它。

    具有使用简单,灵活等特点。不足的地方,不可以自定义刷新的头部和加载更多功能。

    2、实例化此控件的Activity应添加一个 OnRefreshListener,以便在完成滑动刷新手势时收到通知。

    SwipeRefreshLayout 会在每次手势再次完成时通知监听器,监听器负责确定何时实际启动其内容的刷新。如果监听器不需要有刷新动作,通过调用 setRefreshing(false) 来取消任何刷新的视觉指示。如果用户要禁用手势和进度动画,可以通过调用 setEnabled(false)实现。

    3、SwipeRefreshLayout 经常与ListView RecyclerView CardView控件一起使用,用来刷新数据显示。

    SwipeRefreshLayout 在xml文件中角色:它作为手势刷新视图的父布局控件,并且只支持一个直接子控件。

    4、常用的API
    方法 说明
    setRefreshing(boolean refreshing) 设置刷新状态,true表示正在刷新,false表示取消刷新。
    isRefreshing() 判断当前的状态是否是正处于刷新状态。
    setSize(int size) 设置下拉刷新图标的大小, 只支持两种: DEFAULT 和 LARGE
    setColorSchemeResources(int…colorReslds) 设置进度View的组合颜色,在手指上下滑时使用第一个颜色,在刷新中,会一个个颜色进行切换
    setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener listener) 设置监听,需要重写onRefresh()方法,顶部下拉时会调用这个方法,在里面实现请求数据的逻辑,设置下拉进度条消失等等。
    setProgressViewOffset(boolean scale, int start, int end) 设置动画样式下拉的起始点和结束点,scale设置是否需要放大或者缩小动画, 第一个参数:默认为false,设置为true,下拉过程中刷新图标就会从小变大 第二个参数:起始位置,刷新图标距离顶部像素px 第三个参数:结束位置,刷新图标距离顶部像素px
    setProgressViewEndTarget(boolean scale, int end) 设置动画样式下拉的结束点 scale设置是否需要放大或者缩小动画, 第二个参数:结束位置,刷新图标距离顶部像素px
    setSlingshotDistance(@Px int slingshotDistance) 设置可以将刷新指示器拉出其静止位置的距离(以像素为单位)
    setEnabled(boolean enabled) false:禁用手势下拉刷新动画
    三、创建activity_swipe_recycler.xml与空类SwipeRecyclerActivity
    1、在app的build.gradle配置文件里导入
     implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
    
    2、activity_swipe_recycler.xml
    <?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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/purple_500"
            app:popupTheme="@style/ToolbarPopupTheme"
            app:theme="@style/ThemeOverlay.AppCompat.Dark"
            app:titleTextColor="@android:color/white" />
    
        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
            android:id="@+id/swipe_refresh_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="10dp">
    
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
    
        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
    
    </LinearLayout>
    

    布局主要一个SwipeRefreshLayout外包一个RecyclerView

    四、创建Adapter与Adapter布局
    1、adapter_load_more.xml
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:card_view="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="60dp">
    
        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            card_view:cardCornerRadius="8dp">
    
            <TextView
                android:id="@+id/tv_item"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="1"
                android:textColor="#D4237A"
                android:textSize="25sp" />
    
        </androidx.cardview.widget.CardView>
    
    </RelativeLayout>
    
    2、创建 LoadMoreAdapter
    public class LoadMoreAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        private List<String> dataList;
    
        // 普通布局
        private final int TYPE_ITEM = 1;
        // 脚布局
        private final int TYPE_FOOTER = 2;
        // 当前加载状态,默认为加载完成
        private int loadState = 2;
        // 正在加载
        public final int LOADING = 1;
        // 加载完成
        public final int LOADING_COMPLETE = 2;
        // 加载到底
        public final int LOADING_END = 3;
    
        public LoadMoreAdapter(List<String> dataList) {
            this.dataList = dataList;
        }
    
        @Override
        public int getItemViewType(int position) {
            // 最后一个item设置为FooterView
            if (position + 1 == getItemCount()) {
                return TYPE_FOOTER;
            } else {
                return TYPE_ITEM;
            }
        }
    
        @NonNull
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            if (viewType == TYPE_ITEM) {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_load_more, parent, false);
                return new RecyclerViewHolder(view);
            } else if (viewType == TYPE_FOOTER) {
                View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_refresh_footer, parent, false);
                return new FootViewHolder(view);
            }
            return null;
        }
    
        @Override
        public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
            if (holder instanceof RecyclerViewHolder){
                RecyclerViewHolder recyclerViewHolder = (RecyclerViewHolder) holder;
                recyclerViewHolder.tvItem.setText(dataList.get(position));
            }else if (holder instanceof FootViewHolder){
                FootViewHolder footViewHolder = (FootViewHolder) holder;
                switch (loadState){
                    case LOADING:// 正在加载
                        footViewHolder.pbLoading.setVisibility(View.VISIBLE);
                        footViewHolder.tvLoading.setVisibility(View.VISIBLE);
                        footViewHolder.llEnd.setVisibility(View.GONE);
                        break;
                    case LOADING_COMPLETE: // 加载完成
                        footViewHolder.pbLoading.setVisibility(View.INVISIBLE);
                        footViewHolder.tvLoading.setVisibility(View.INVISIBLE);
                        footViewHolder.llEnd.setVisibility(View.GONE);
                        break;
                    case  LOADING_END:// 加载到底
                        footViewHolder.pbLoading.setVisibility(View.GONE);
                        footViewHolder.tvLoading.setVisibility(View.GONE);
                        footViewHolder.llEnd.setVisibility(View.VISIBLE);
                        break;
                }
            }
        }
    
        @Override
        public int getItemCount() {
            return dataList.size()+1;
        }
    
    
        private class RecyclerViewHolder extends RecyclerView.ViewHolder {
    
            TextView tvItem;
    
            RecyclerViewHolder(View itemView) {
                super(itemView);
                tvItem = itemView.findViewById(R.id.tv_item);
            }
        }
    
        @Override
        public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
            super.onAttachedToRecyclerView(recyclerView);
            RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
            if (layoutManager instanceof GridLayoutManager){
                final GridLayoutManager gridLayoutManager = (GridLayoutManager)layoutManager;
                gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                    @Override
                    public int getSpanSize(int position) {
                        // 如果当前是footer的位置,那么该item占据2个单元格,正常情况下占据1个单元格
                        return getItemViewType(position) == TYPE_FOOTER ? gridLayoutManager.getSpanCount():1;
                    }
                });
            }
        }
    
        private class FootViewHolder extends RecyclerView.ViewHolder {
            ProgressBar pbLoading;
            TextView tvLoading;
            LinearLayout llEnd;
    
            public FootViewHolder(@NonNull View itemView) {
                super(itemView);
                pbLoading = itemView.findViewById(R.id.pb_loading);
                tvLoading = itemView.findViewById(R.id.tv_loading);
                llEnd = itemView.findViewById(R.id.ll_end);
            }
        }
        /**
         * 设置上拉加载状态
         *
         * @param loadState 0.正在加载 1.加载完成 2.加载到底
         */
        public void setLoadState(int loadState){
            this.loadState = loadState;
            notifyDataSetChanged();
        }
    }
    
    五、在SwipeRecyclerActivity里进行初始化与加载数据
    1、SwipeRecyclerActivity的具体实现
    public class SwipeRecyclerActivity extends AppCompatActivity {
    
        private Toolbar toolbar;
        private SwipeRefreshLayout swipeRefreshLayout;
        private RecyclerView recyclerView;
        private LoadMoreAdapter loadMoreAdapter;
        private List<String> dataList = new ArrayList<>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_swipe_recycler);
            init();
        }
    
        private void init() {
            toolbar = findViewById(R.id.toolbar);
            swipeRefreshLayout = findViewById(R.id.swipe_refresh_layout);
            recyclerView = findViewById(R.id.recycler_view);
    
            // 使用Toolbar替换ActionBar
            setSupportActionBar(toolbar);
    
            // 设置刷新控件颜色
            swipeRefreshLayout.setColorSchemeColors(Color.parseColor("#4DB6AC"));
    
            // 模拟获取数据
            getData();
            loadMoreAdapter = new LoadMoreAdapter(dataList);
            recyclerView.setLayoutManager(new LinearLayoutManager(this));
            recyclerView.setAdapter(loadMoreAdapter);
    
            // 设置下拉刷新
            swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
                @Override
                public void onRefresh() {
                    // 刷新数据
                    if (dataList.size()>0){
                        dataList.clear();
                    }
                    getData();
                    loadMoreAdapter.notifyDataSetChanged();
    
                    // 延时1s关闭下拉刷新
                    swipeRefreshLayout.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            if (swipeRefreshLayout != null && swipeRefreshLayout.isRefreshing()) {
                                swipeRefreshLayout.setRefreshing(false);
                            }
                        }
                    }, 2000);
                }
            });
    
            // 设置加载更多监听
            recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener() {
                @Override
                public void onLoadMore() {
                    loadMoreAdapter.setLoadState(loadMoreAdapter.LOADING);
    
                    if (dataList.size() < 52) {
                        // 模拟获取网络数据,延时1s
                        new Timer().schedule(new TimerTask() {
                            @Override
                            public void run() {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        getData();
                                        loadMoreAdapter.setLoadState(loadMoreAdapter.LOADING_COMPLETE);
                                    }
                                });
                            }
                        }, 2000);
                    } else {
                        // 显示加载到底的提示
                        loadMoreAdapter.setLoadState(loadMoreAdapter.LOADING_END);
                    }
                }
            });
        }
    
        private void getData() {
            String letter ="Item";
            for (int i = 0; i < 30; i++) {
                dataList.add(letter+i);
            }
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            MenuInflater menuInflater = getMenuInflater();
            menuInflater.inflate(R.menu.layout_menu, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
                case R.id.liner:
                    recyclerView.setLayoutManager(new LinearLayoutManager(this));
                    break;
    
                case R.id.grid:
                    recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
                    break;
            }
            dataList.clear();
            getData();
            recyclerView.setAdapter(loadMoreAdapter);
            return super.onOptionsItemSelected(item);
        }
    }
    
    2、EndlessRecyclerOnScrollListener的抽象类实现
    public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
        // 用来标记是否正在向上滑动
        private boolean isSlidingUpward = false;
    
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
            //当recyclerview 不滑动时
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                // 获取最后一个完全显示的itemPosition
                int lastItemPosition = layoutManager.findLastCompletelyVisibleItemPosition();
                int itemCount = layoutManager.getItemCount();
    
                // 判断是否滑动到了最后一个item,并且是向上滑动
                if (lastItemPosition == (itemCount - 1) && isSlidingUpward) {
                    // 加载更多
                    onLoadMore();
                }
    
            }
        }
    
        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            // 大于0表示正在向上滑动,小于等于0表示停止或向下滑动
            isSlidingUpward = dy > 0;
        }
    
        //加载更多回调
        public abstract void onLoadMore();
    }
    

    完整代码:https://gitee.com/zyd_gitee/recycler-view-refresh-demo.git

    1.gif

    相关文章

      网友评论

          本文标题:SwipeRefreshLayout+RecyclerView实

          本文链接:https://www.haomeiwen.com/subject/njcjcdtx.html