recyclerView的写法--实现长按item弹出菜单功能,每个item实现偏移

导入到工程中

方式一:

在你的工程上点击右键,弹出如下图片,大家看图吧
1.右键工程名,选中Modulder setting
右键工程名,选中Modulder setting
2.点击app,再选中dependence
在这里插入图片描述
3.找到右边的加号,选中library
在这里插入图片描述
4.搜索框中输入recycler
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020092816190891.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0JhcnJ5amFja2V0,size_16,color_FFFFFF,t_70#pic_center

点击ok后,这个recyclerview-v7的包就引用到自己的工程里了,也不用管那个build.jradle文件了,打开会发现已经自动填好了.
方式二:
打开app/build.gradle文件,在dependcies中添加如下内容

compile 'com.android.support:recyclerview-v7:24.0.0'

注意对于AS为3.6版本,SDK版本大于28的建议使用

implementation 'androidx.recyclerview:recyclerview:1.0.0'

recyclerView的使用

在活动中成功使用recyclerView要设置两个参数,布局和适配器。
如果要实现长按弹出菜单的功能,要调用registerForContextMenu(View v);这个函数。同时,适配器的ViewHolder类要实现响应的接口View.OnCreateContextMenuListener接口。

onBindViewHolder方法中要实现RecyclerView控件中每一个item View的大部分功能。因为 onBindViewHolder的执行是在创建ViewHolder,且已知itemView的个数后才调用的。

rvContract = (RecyclerView) findViewById(R.id.rvContract);
//传入线性布局
rvContract.setLayoutManager(new LinearLayoutManager(this));
mList = new ArrayList<>();
mAdapter = new ContactAdapter(this, mList);
rvContract.setAdapter(mAdapter);
registerForContextMenu(rvContract);
/**
 * 长按item弹出菜单后,点击某一菜单项会回调这一方法
 * item中带有一个intent属性。
 * itemId对应着菜单的id
 *
 * @param item 所点击的菜单项
 * @return
 */
@Override
public boolean onContextItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case 0://修改
         break;
        case 1://删除
            deleteContact(item);
            break;
    }
    return super.onContextItemSelected(item);
}

实现rv的适配器类,由于rv的封装就要求有viewHolder类,故可以先写内部静态类ContractViewHolder extends RecyclerView.ViewHolder。

/**
 * @ 功能适配器中必须要有实体类,也是bean
 * 1.数据的绑定,2.创建viewHolder--布局加载器--上下文对象
 * Ctreate by barry on 2020/9/20.
 */
public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContractViewHolder> {
    private Context mContext;//null
    private List<ContactBean> mList;//null
    private LayoutInflater mInflater;//null

    private static final String POSITION_KEY ="POSITION_KEY";

    public ContactAdapter(Context mContext, List<ContactBean> mList) {
        this.mContext = mContext;
        this.mList = mList;
        mInflater = LayoutInflater.from(mContext);
    }

    /**
     * 创建ViewHolder实例,并将item布局加载进入
     * @param parent
     * @param viewType
     * @return
     */
    @NonNull
    @Override
    public ContractViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        //加载item布局
        View view = mInflater.inflate(R.layout.recyclerview_item_contact,parent,false);
        ContractViewHolder viewHolder = new ContractViewHolder(view);
        return viewHolder;
    }

    /**
    
     * 对vieholder对象进行数据赋值
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(@NonNull ContractViewHolder holder, int position) {
        ContactBean contact = mList.get(position);
        holder.tvName.setText(contact.getName());
        holder.tvPhone.setText(contact.getPhone());

    }

    /**
     * 统计item个数
     * 如果直接返回一个固定的数字,就会有一些空的item项
     * @return
     */
    @Override
    public int getItemCount() {
        return mList.size();
    }

    static class ContractViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener{
        private TextView tvName;//null
        private TextView tvPhone;//null

        public ContractViewHolder(@NonNull View itemView) {
            super(itemView);
            tvName = (TextView)itemView.findViewById(R.id.tv_name);
            tvPhone = (TextView)itemView.findViewById(R.id.tv_phone);
            //由于recycleView没有实现长按弹出菜单的接口,要在ViewHolder中自己实现该接口
            //setOnCreateContextMenuListener(OnCreateContextMenuListener l)
            // 由于ContractViewHolder已经实现该接口,故直接传入this
            itemView.setOnCreateContextMenuListener(this);

        }
        //创建响应的菜单

        @Override
        public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
            //获取当前所按的item的下标,回传到MainActivity中供onContextItemSelected使用。
            int position = getAdapterPosition();
            Intent intent = new Intent();//这里不需要使用intent,来跳转
            intent.putExtra(POSITION_KEY,position);

            menu.setHeaderTitle("编剧");
            //菜单的选项时通过add来直接添加,通过setIntent(),让每一个MenuItem自带了一个intent
            menu.add(0,0,0,"修改").setIntent(intent);
            menu.add(0,1,0,"删除").setIntent(intent);

        }
    }
}

创建一个实体类来存储item内容。
注意,为了让bean的数据能在活动之间相互传输,要实现序列化1.seriable 2.Parcelable。安卓提供了序列化的插件。
参考如何使用Parcelable完成序列化操作

/**由于要在不同的活动之间进行传递,该类必须实现序列化1.seriable 2.Parcelable
 * @ 功能
 * Ctreate by barry on 2020/9/22.
 */
public class ContactBean implements Parcelable {
    private int id;
    private String name;
    private String phone;

item的偏移,实现更好的视觉效果。

主要是调用addItemDecoration()方法,该方法需要传入一个ItemDecoration对象。
在安卓中,系统已经实现了ItemDecoration的实现类,DividerItemDecoration类。

DividerItemDecoration.HORIZONTAL
表示在水平列之间加间隔
DividerItemDecoration.VERTICAL
表示在竖直列之间加间隔

mRvGrid.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.HORIZONTAL));

该类的缺点:每个偏移的间隔只有1dp.如果要大一点的间隔偏移,还是要自己定义一个类来继承ItemDecoration。
GridSpaceItemDecoration.java

public class GridSpaceItemDecoration extends RecyclerView.ItemDecoration {
    private int mSpace;

    public GridSpaceItemDecoration(int mSpace) {
        this.mSpace = mSpace;
    }

    /**
     * 设置itemView的偏移量,每一个itemView都会调用这一函数
     * @param outRect Item的矩形边界
     * @param view ItemView
     * @param parent  RecyclerView
     * @param state RecyclerView的状态
     */
    @Override
    public void getItemOffsets(@NonNull Rect outRect,
                               @NonNull View view, @NonNull RecyclerView parent,
                               @NonNull RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        //每一个itemView 左侧都有一个距离
        outRect.left = mSpace;
    }
}

偏移量会使得未偏移的itemView的宽度或者高度会减少偏移量dp.
效果如下
在这里插入图片描述
同时可以通过移动View,来使第一幅的左边框消失。

  private void getRecyclerViewOffset(RecyclerView parent){
//        View 的margin
//        margin 为正 ,则View会距离边界产生一个距离
//        margin 为负 ,则View会超出边界产生一个距离
        LinearLayout.LayoutParams  layoutParams= (LinearLayout.LayoutParams) parent.getLayoutParams();
        layoutParams.leftMargin = -mSpace;
        parent.setLayoutParams(layoutParams);
    }

在构造器中调用该函数。

public GridSpaceItemDecoration(int mSpace, RecyclerView parent) {
    this.mSpace = mSpace;
    getRecyclerViewOffset(parent);
}
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页