RecyclerView的使用

目录

  一、配置RecyclerView
   二、使用RecyclerView
   三、RecyclerView的分割线
   四、RecyclerView的Adapter
   五、RecyclerView的点击事件
     5.1、在Adapter中实现
     5.2、在Activity(Fragment)中实现
   六、RecyclerView实现GridView
   七、RecyclerView实现瀑布流
   八、RecyclerView设置头视图、足视图、空视图

一、配置RecyclerView

  首先要导入support-v7包,在app的build.gradle中加入如下代码导包,然后async工程一下:

dependencies {
    ...
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support:recyclerview-v7:28.0.0'
}

二、使用RecyclerView

在XML中

 <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

在Activity中或者Fragment中代码

 private void initView() {
        RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recycler);
        LinearLayoutManager manager = new LinearLayoutManager(mContext);
        //布局管理器设置排列样式
       // manager.setOrientation(LinearLayoutManager.HORIZONTAL);
        manager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(manager);
        //设置item增加和删除时的动画
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        //设置分割线
        mRecyclerView.addItemDecoration(new DividerItemDecoration(mContext,DividerItemDecoration.VERTICAL_LIST));
        mAdapter = new RecyclerViewAdapter(mContext,mListData);
        mRecyclerView.setAdapter(mAdapter);
    }

三、RecyclerView的分割线
   //设置分割线
        mRecyclerView.addItemDecoration(new DividerItemDecoration(mContext,DividerItemDecoration.VERTICAL_LIST));

  RecyclerView自身属性没有默认的分割线,需要我们继承RecyclerView.ItemDecoration来自定义分割线:


public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private static final int[] ATTRS = new int[]{
            android.R.attr.listDivider
    };

    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

    private Drawable mDivider;

    private int mOrientation;

    public DividerItemDecoration(Context context, int orientation) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
        setOrientation(orientation);
    }

    public void setOrientation(int orientation) {
        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
            throw new IllegalArgumentException("invalid orientation");
        }
        mOrientation = orientation;
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            drawVertical(c, parent);
        } else {
            drawHorizontal(c, parent);
        }

    }


    public void drawVertical(Canvas c, RecyclerView parent) {
        final int left = parent.getPaddingLeft();
        final int right = parent.getWidth() - parent.getPaddingRight();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            RecyclerView v = new RecyclerView(parent.getContext());
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    public void drawHorizontal(Canvas c, RecyclerView parent) {
        final int top = parent.getPaddingTop();
        final int bottom = parent.getHeight() - parent.getPaddingBottom();

        final int childCount = parent.getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = parent.getChildAt(i);
            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicHeight();
            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(c);
        }
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
        if (mOrientation == VERTICAL_LIST) {
            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
        } else {
            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
        }
    }
}

  这里核心方法时OnDraw,它根据传进来的orientation来判断绘制横向item或者纵向item的分割线,drawVertical()用于绘制纵向item的分割线, drawHorizontal()用于绘制横向item的分割线, getItemOffsets()用于设置item的padding属性。
但是重点在于:设置分割线,一定,一定在set Adapter之前加入,根据不同的Recycler View有不同的分割线,在下面的Recycler View实现中会有讲解。


四、RecyclerView的Adapter

  RecyclerView的Adapter最大的改进时增加了ViewType,会根据不同的View Type加载不同的item布局。使用Adapter可以分为四步吧(对于小菜鸟的写法,大神封装宁说)。

1、写一个Adapter类去继承RecyclerView.Adapter<>

   public class RecyclerViewAdapter extends RecyclerView.Adapter<T>

2、写一个ViewHolder内部类去继承RecyclerView.ViewHolder,在内部类中声明控件,并将这个类传入Adapter类的泛型中

static class ViewHolder extends RecyclerView.ViewHolder {

        TextView mItemIndexTv;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            mItemIndexTv = (TextView) itemView.findViewById(R.id.item_tv);
        }
    }

3、重写onCreateViewHolder()、onBindViewHolder()、getItemCount()方法

@NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        if (mContext == null) {
            mContext = viewGroup.getContext();
        }
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_recycler, viewGroup, false);
        ViewHolder holder = new ViewHolder(view);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int position) {
        viewHolder.mItemIndexTv.setText(mListData.get(position));

        if(mOnItemClickListener != null){
            viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    int pos = viewHolder.getLayoutPosition();
                 mOnItemClickListener.OnItemClick(viewHolder.itemView,pos);
                }
            });
            viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    int pos = viewHolder.getLayoutPosition();
                    mOnItemClickListener.OnItemLongClick(viewHolder.itemView,pos);
                    return false;
                }
            });
        }


    }

    @Override
    public int getItemCount() {
        return mListData != null ? mListData.size() : 0;
    }

4、构造函数和自己定义方法。

public RecyclerViewAdapter(Context mContext, List<String> mListData) {
        this.mContext = mContext;
        this.mListData = mListData;
    }
    
    /**
     * 数据更新
     */

    public void upData(List<String> listData) {
        if (listData != null) {
            mListData.addAll(listData);
        }
        notifyDataSetChanged();
    }

    /**
     * 数据清除
     */
    public void cleanData() {
        if (mListData != null && mListData.size() > 0) {
            mListData.clear();
            notifyDataSetChanged();
        }
    }

    /**
     * 增加对应位置的数据
     */
    public void addData(int position, List<String> listData) {
        if (listData != null && listData.size() > 0) {
            mListData.addAll(position, listData);
            notifyDataSetChanged();
        }
    }

    /**
     * 删除指定位置的数据
     */
    public void removeData(int position){
        mListData.remove(position);
        notifyDataSetChanged();
    }

完整的Adapter类如下:

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {

    private Context mContext;
    private List<String> mListData;

    public RecyclerViewAdapter(Context mContext, List<String> mListData) {
        this.mContext = mContext;
        this.mListData = mListData;
    }

    /**
     * 数据更新
     */

    public void upData(List<String> listData) {
        if (listData != null) {
            mListData.addAll(listData);
        }
        notifyDataSetChanged();
    }

    /**
     * 数据清除
     */
    public void cleanData() {
        if (mListData != null && mListData.size() > 0) {
            mListData.clear();
            notifyDataSetChanged();
        }
    }

    /**
     * 增加对应位置的数据
     */
    public void addData(int position, List<String> listData) {
        if (listData != null && listData.size() > 0) {
            mListData.addAll(position, listData);
            notifyDataSetChanged();
        }
    }

    /**
     * 删除指定位置的数据
     */
    public void removeData(int position){
        mListData.remove(position);
        notifyDataSetChanged();
    }


    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        if (mContext == null) {
            mContext = viewGroup.getContext();
        }
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_recycler, viewGroup, false);
        ViewHolder holder = new ViewHolder(view);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int position) {
        viewHolder.mItemIndexTv.setText(mListData.get(position));
    }

    @Override
    public int getItemCount() {
        return mListData != null ? mListData.size() : 0;
    }

    static class ViewHolder extends RecyclerView.ViewHolder {

        TextView mItemIndexTv;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            mItemIndexTv = (TextView) itemView.findViewById(R.id.item_tv);
        }
    }

}

然后在Activity中或者Fragment中声明Adapter和设置Adapter:

  RecyclerViewAdapter mAdapter = new RecyclerViewAdapter(mContext,mListData);
        mRecyclerView.setAdapter(mAdapter);

五、RecyclerView的点击事件

  RecyclerView不能像ListView一样有itemClick的监听,需要我们自己实现。

5.1、在Adapter中实现

在设置Adapter中我们指定了ViewHolder,ViewHolde代表的是RecyclerView的单条,而ViewHolder中有一个itemView,所指的就是RecyclerView的单条,所以我们只需要设置holder.itemView的点击事件,就是RecyclerView的单条点击事件。

 @Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int position) {
        viewHolder.mItemIndexTv.setText(mListData.get(position));
        //单点击事件
        viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(mContext,"点击了第"+ position,Toast.LENGTH_SHORT).show();
            }
        });
        //长点击事件
        viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                Toast.makeText(mContext,"进行长点击、点击了第"+ position,Toast.LENGTH_SHORT).show();
                return false;
            }
        });
      }
5.2、在Activity(Fragment)中实现

想要像ListView在Activity(Fragment)中实现RecyclerView的点击事件,需要使用接口回调。
基本步骤有四步:
1、定义接口

public interface OnItemClickListener {
    //单点监听
    void OnItemClick(View view,int position);
    //长点监听
    void OnItemLongClick(View view,int position);
}

2、在Adapter中声明接口并设置监听

  private OnItemClickListener mOnItemClickListener;
  public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
        this.mOnItemClickListener = mOnItemClickListener;
    }

3、对item进行点击事件监听并回调给我么自定义的监听

@Override
    public void onBindViewHolder(@NonNull final ViewHolder viewHolder, final int position) {
        viewHolder.mItemIndexTv.setText(mListData.get(position));
        

        if(mOnItemClickListener != null){
            viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    int pos = viewHolder.getLayoutPosition();
                 mOnItemClickListener.OnItemClick(viewHolder.itemView,pos);
                }
            });
            viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View view) {
                    int pos = viewHolder.getLayoutPosition();
                    mOnItemClickListener.OnItemLongClick(viewHolder.itemView,pos);
                    return false;
                }
            });
        }
    }

4、在Activity(Fragment)中实现点击逻辑

 mAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void OnItemClick(View view, int position) {
                Toast.makeText(RecyclerViewActivity.this,"点击了第"+ position + "条",Toast.LENGTH_SHORT).show();
            }

            @Override
            public void OnItemLongClick(View view, final int position) {
                new AlertDialog.Builder(RecyclerViewActivity.this)
                        .setTitle("确认删除")
                        .setNegativeButton("取消",null)
                        .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                mAdapter.removeData(position);
                            }
                        })
                        .show();
            }
        });

六、RecyclerView实现GridView
  mRecyclerView.addItemDecoration(new DividerGridItemDecoration(this));
        GridLayoutManager manager = new GridLayoutManager(this,3);
        mRecyclerView.setLayoutManager(manager);

设置Manager为GridLayoutManager,第一个参数为上下文,第二个参数为GridView列数,这里使用的分割线的类会在DEMO代码中给出,欢迎下载
实现效果:
在这里插入图片描述


七、RecyclerView实现瀑布流

指定RecyclerView的Manager为StaggeredGridLayoutManager,第一个参数为瀑布流的列数,第二个参数为瀑布流的方向。

  StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(manager);

八、RecyclerView添加头视图、足视图、空视图

RecyclerView没有像ListView一样给我们提供addHeaderView()和addFooterView()、setEmptyView()的方法,需要需要我们自己进行封装,比较好的是RecyclerView给我们提供了丰富的Adapter可进行拓展,Adapter中可根据不同的View Type去加载不同的视图,这样就给我们暴露出一个接口了
这里找了一个大神的博客,他写的很详细了, 大家可以看看
https://www.jianshu.com/p/0eebc6c2a08d
他的思路也写的比较详细。我们不光会要用,还要知道其中的原理。

这里我只写出如何使用
1、添加依赖:

 implementation 'com.xpc:gloriousrecyclerview:0.2.6@aar'
    implementation 'com.android.support:recyclerview-v7:24.2.1'

2、xml使用

<com.xpc.gloriousrecyclerview.GloriousRecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:hideNoMoreData="true"
        app:loadAllCompleteText="Load Complete"
        app:loadMoreBackground="#ccc"
        app:loadMoreFailedText="加载失败..."
        app:loadMoreIndeterminateDrawable="@drawable/loading_icon_drawable"
        app:loadMoreTextColor="#0080ff"
        app:loadMoreTextSize="14sp"
        app:loadingMoreText="加载中..请稍后"/>

3、在Activity(Fragment)中

public class HeadAndFooterRecyclerViewActivity extends AppCompatActivity {


    private GloriousRecyclerView mRecycler;
    private List<String> mListData = new ArrayList<>();
    private RecyclerViewAdapter mAdapter;
    private View mHeadView, mFooterView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_head_and_footer_recycler_view);
        initHeadAndFooterView();
        initView();
        initData();
    }
    
    private void initData() {
        for (int i = 0; i < 10; i++) {
            mListData.add(i + "");
        }
        mAdapter.upData(mListData);
    }

    private void initView() {
        mRecycler = (GloriousRecyclerView) findViewById(R.id.recycler_view);
        LinearLayoutManager manager = new LinearLayoutManager(this);
        manager.setOrientation(LinearLayoutManager.VERTICAL);
        mRecycler.setLayoutManager(manager);

        mAdapter = new RecyclerViewAdapter(this, mListData);
        mRecycler.setAdapter(mAdapter);
        
       mRecycler.addHeaderView(mHeadView);
        mRecycler.addFooterView(mFooterView);
        mRecycler.setEmptyView(emptyView);
    }

    private void initHeadAndFooterView() {
        mHeadView = LayoutInflater.from(this).inflate(R.layout.recycler_head, mRecycler, false);
        mFooterView = LayoutInflater.from(this).inflate(R.layout.recycler_footer, mRecycler, false);
        emptyView = LayoutInflater.from(this).inflate(R.layout.recycler_empty,mRecycler,false);
    }

}

使用效果图:
在这里插入图片描述

这就是大概的使用,作者的GitHub中提供的DEMO功能更多,下拉刷新、上拉加载,大家如果需要的话可以自己去学习,这里提供出Git地址:
https://github.com/titanchen2000/GloriousRecyclerView

不过有一些缺陷的是:使用这个控件,只能添加一层的头视图和足视图,无法添加多层,在后续中我会进行修改,欢迎关注。谢谢。

希望这篇博客能帮助到你!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值