美文网首页
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实

    前提: 现在市面上的Android的App只要涉及到网络交互的,几乎都有着上拉刷新的功能。无论是新闻资讯类的简书掘...

  • SwipeRefreshLayout+RecyclerView实

    一、介简 上一节写自定义RecyclerView实现了一个简单的下拉刷新与加载更多,这一节主要写外包Recycle...

  • RecyclerView之EmptyView展示

    SwipeRefreshLayout+RecyclerView之EmptyView展示 创建EmptyView的布...

  • SwipeRefreshLayout+Recyclerview

    上拉加载更多实现方式: 参考文章:https://www.jianshu.com/p/96f14f6a5bb4 参...

  • Android 用SwipeRefreshLayout+Recy

    开篇   工作闲暇之余,用SwipeRefreshLayout+RecyclerView倾心打造了一个下拉刷新控件...

  • SwipeRefreshLayout+RecyclerView滑

    偶然间发现的bug 场景如下:recyclerView使用了头部view的逻辑。具体adapter就不介绍了,具体...

  • SwipeRefreshLayout+RecyclerView冲

    场景1 一种是SwipeRefreshLayout+RecyclerView在同一个界面的,可以通过重写swipe...

  • 虚与实

    实而虚之,虚而实之,实而实之,虚而虚之,先虚后实,先实后虚,外虚内实,外实内虚,虚虚实实,虚实相乱等,都是虚实...

  • 看完电影《头号玩家》写了一首小诗《实》 虚幻之雾压向地面, 灰色的霭笼罩大地, 四周是虚,还是实 ? 摸索向前走,...

网友评论

      本文标题:SwipeRefreshLayout+RecyclerView实

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