RecyclerView简单案例&添加下拉刷新(SwipeRefreshLayout)、上拉加载(lastVisibleItem)

来源:互联网 发布:波士顿矩阵的特点 编辑:程序博客网 时间:2024/05/17 01:05

效果图如下


这里写图片描述

一、先看各个布局

  1. activity_main
    使用SwipeRefreshLayout包裹RecyclerView

    <LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <android.support.v4.widget.SwipeRefreshLayout        xmlns:android="http://schemas.android.com/apk/res/android"        android:id="@+id/srl"        android:layout_width="match_parent"        android:layout_height="match_parent">        <android.support.v7.widget.RecyclerView            android:id="@+id/rv"            android:layout_width="match_parent"            android:layout_height="match_parent"/>    </android.support.v4.widget.SwipeRefreshLayout></LinearLayout>
  2. list_item
    只显示一个一个字符串

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="vertical" >    <TextView        android:id="@+id/tv_text"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center"        android:padding="15dp"        android:textSize="18sp" />    <View        android:layout_width="match_parent"        android:layout_height="1dp"        android:background="#fcc" /></LinearLayout>
  3. list_foot
    最后一个条目可见时加载更多数据(一个loading和文字提示)

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:gravity="center_vertical"              android:orientation="horizontal"              android:padding="10dp">    <ProgressBar        android:id="@+id/pb_loading"        style="@android:style/Widget.ProgressBar.Inverse"        android:layout_width="26dp"        android:layout_height="26dp"        android:layout_marginLeft="130dp"/>    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginLeft="20dp"        android:text="松开加载"        android:textColor="#c0f0"        android:textSize="20sp"/></LinearLayout>

二、适配器的实现(★)

  1. RecyclerView的适配器(要熟练掌握哦)
    分析数据应该如何展示,完整代码紧跟在分析之后

    1. 怎么区分当前位置要展示的具体布局类型
      ListView中我们很熟悉了,通过getViewTypeCount(): Int获取需要展示的布局数目(如2),然后通过getItemViewType(): Int获取当前位置需要展示的具体布局类型
      ↑ VS ↓
      RecyclerView中仅使用getItemViewType(): Int即可获得当前位置对应的布局类型,用法和ListView的getItemViewType(): Int别无它异,具体参考下面的完整代码

    2. ViewHolder如何创建
      ListView中需要手动创建静态Holder,并在getView(): View中先后手动setTag()getTag()来获取holder,然后进行控件内容的填充
      ↑ VS ↓
      RecyclerView已帮我们集成进了ViewHolder(这也是Recycler的核心),只要继承RecyclerView.Adapter时添加泛型RecyclerView.ViewHolder,然后分别添加各布局对应的Holder类(类中初始化控件),最后在onCreateViewHolder: RecyclerView.ViewHolder中通过各布局类型创建对应的Holder实例即可

    3. 如何通过ViewHolder填充数据
      ListView中在getView(): View的缓存复用、holder的setTag()完成后直接进行控件内容的填充
      ↑ VS ↓
      RecyclerView中,我们单独在onBindViewHolder(holder): void方法中通过转换holder类型后进行控件内容的填充

    public class SampleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {    // 要展示的数据集合    private List<String> mDatas;    // 判断布局类型    private static final int TYPE_ITEM = 0;    private static final int TYPE_FOOT = 1;    /**     * 初始化工作(在这里是获得了数据集合)     */    public SampleAdapter(List<String> datas) {        mDatas = datas;    }    /**     * 当前位置应该展示的条目布局的类型     */    @Override public int getItemViewType(int position) {        // 数据集合最后一行数据之后的那一行就应该加载脚布局        if (position + 1 == getItemCount()) {            return TYPE_FOOT;        } else {            return TYPE_ITEM;        }    }    /**     * 设置各布局,并返回与其对应的ViewHolder实例     */    @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View view = null;        RecyclerView.ViewHolder holder = null;        if (viewType == TYPE_ITEM) {            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, null);            holder = new ItemHolder(view);        } else if (viewType == TYPE_FOOT) {            view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_foot, null);            holder = new FootHolder(view);        } else {            // 默认的布局及其对应的ViewHolder实例,防止发生意外            // default view = ...            // default holder = ...        }        return holder;    }    /**     * 填充各布局的控件内容     */    @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {        if (holder instanceof ItemHolder) {            ((ItemHolder) holder).tvText.setText(String.valueOf(mDatas.get(position)));        }    }    /**     * 要展示的条目总数(包括所有数据集合和额外添加的头、身、脚条目数量)     */    @Override public int getItemCount() {        return mDatas.size() + 1;    }    /****************************************     * 各布局类型的ViewHolder     */    class FootHolder extends RecyclerView.ViewHolder {        public FootHolder(View view) {            super(view);        }    }    class ItemHolder extends RecyclerView.ViewHolder {        // 展示一行字符串        @BindView(R.id.tv_text) TextView tvText;        public ItemHolder(View view) {            super(view);            ButterKnife.bind(this, view);        }    }}

三、Activity中如何展示并添加刷新和加载逻辑

注意数据集合发生变化,需要使用mAdapter.notifyItemRemoved(position)来告知适配器以进行界面刷新

public class MainActivity extends BaseActivity {    @BindView(R.id.srl) SwipeRefreshLayout srl;    @BindView(R.id.rv) RecyclerView rv;    /**     * 布局管理器     * 1. LinearLayoutManager:支持横向、纵向     * 2. GridLayoutManager:网格     * 3. StaggeredGridLayoutManager:瀑布流     */    private LinearLayoutManager mLayoutManager;    private List<String> mDatas;    private SampleAdapter mAdapter;    // 记录最后可见条目    private int lastVisible;    // 分别记录刷新和加载次数    int refreshTimes = 0;    int addmoreTimes = 0;    @Override int layoutId() {        return R.layout.activity_main;    }    /**     * 初始化数据     */    @Override void initData() {        mDatas = new ArrayList<String>();        for (int i = 0; i < 15; i++) {            mDatas.add("数据== " + (i + 1) + " ==");        }    }    @Override void initView() {        srl.setColorSchemeResources(R.color.color1, R.color.color2, R.color.color3, R.color.color4);        srl.setOnRefreshListener(this);        rv.setOnScrollListener(new RecyclerView.OnScrollListener() {            @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) {                super.onScrollStateChanged(recyclerView, newState);                // 不在滑动和最后可见条目是脚布局时加载更多                if (newState == RecyclerView.SCROLL_STATE_IDLE && lastVisible + 1 == mAdapter.getItemCount()) {                    addmore();                }            }            @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) {                super.onScrolled(recyclerView, dx, dy);                lastVisible = mLayoutManager.findLastVisibleItemPosition();            }        });        rv.setHasFixedSize(true);        mLayoutManager = new LinearLayoutManager(this);        rv.setLayoutManager(mLayoutManager);        rv.setItemAnimator(new DefaultItemAnimator());        mAdapter = new SampleAdapter(mDatas);        rv.setAdapter(mAdapter);    }    /**     * 模仿下拉刷新     */    @Override void srlRefresh() {        mDatas.add(0, "刷新 " + ++refreshTimes + "次");        new Timer().schedule(new TimerTask() {            @Override public void run() {                runOnUiThread(new Runnable() {                    @Override public void run() {                        Toast.makeText(MainActivity.this, "刷新" + refreshTimes, Toast.LENGTH_SHORT).show();                        srl.setRefreshing(false);                        mAdapter.notifyDataSetChanged();                    }                });            }        }, 1000);    }    /**     * 模仿上拉加载     */    void addmore() {        new Timer().schedule(new TimerTask() {            @Override public void run() {                runOnUiThread(new Runnable() {                    @Override public void run() {                        mDatas.add("数据增加" + ++addmoreTimes);                        Toast.makeText(MainActivity.this, "加载" + addmoreTimes, Toast.LENGTH_SHORT).show();                        mAdapter.notifyItemInserted(mDatas.size());                    }                });            }        }, 1000);    }}
阅读全文
1 0
原创粉丝点击