欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

RecycleView Adapter封装使用

程序员文章站 2022-05-15 19:30:19
...

参照不同大神的博客 , 修改而来, 望大神们海涵!!!!

build.gradle引用

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

适配器主体
这里设置了两种方式设置数据源
1.构造函数传参
2.初始空适配器,出入数据源刷新适配器

public abstract class BaseRecyclerViewAdapter<T> extends RecyclerView.Adapter<BaseRecyclerViewHolder> {
    /*布局ID*/
    private int mLayoutID = -1;
    /*数据源*/
    private List<T> mListData = null;
    /*上下文*/
    private Context mContext = null;
    /*点击事件*/
    private OnItemClickListener mClickListener = null;
    /*单击事件和长单击事件的屏蔽标识*/
    private boolean clickFlag = true;

    /*上下文,布局ID,数据源*/
    public BaseRecyclerViewAdapter(Context context, int layoutId, List<T> data) {
        this.mLayoutID = layoutId;
        this.mListData = data;
        this.mContext = context;
    }

    /*上下文,布局ID*/
    public BaseRecyclerViewAdapter(int mLayoutID, Context mContext) {
        this.mLayoutID = mLayoutID;
        this.mContext = mContext;
    }

    /*设置数据源*/
    public void setData(List<T> data) {
        this.mListData = data;
        notifyDataSetChanged();
    }

    /*在任意位置添加 Item */
    public void addData(int position, T data) {
        mListData.add(position, data);
        //如果想使用动画必用
        notifyItemInserted(position);
    }

    /*移除某位置的数据*/
    public void removeData(int position) {
        mListData.remove(position);
        //如果想使用动画必用
        notifyItemRemoved(position);
    }

    /*创建复用器*/
    @Override
    public BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View inflate = LayoutInflater.from(mContext).inflate(mLayoutID, parent, false);
        inflate.setBackgroundResource(R.drawable.recycle_item);
        final BaseRecyclerViewHolder holder = new BaseRecyclerViewHolder(inflate, mContext);

        /*单击事件回调*/
        inflate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (clickFlag) {
                    if (mClickListener != null) {
                        mClickListener.OnItemClick(v, holder.getLayoutPosition());
                    }
                }
                clickFlag = true;
            }
        });
        //单击长按事件回调
        inflate.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if (mClickListener != null) {
                    mClickListener.OnItemLongClick(v, holder.getLayoutPosition());
                }
                clickFlag = false;
                return false;
            }
        });
        return holder;
    }

    /*绑定ViewHolder*/
    @Override
    public void onBindViewHolder(BaseRecyclerViewHolder holder, int position) {
        convert(holder, mListData.get(position),position);
    }

    protected abstract void convert(BaseRecyclerViewHolder holder, T bean,int position);

    /*获取条目数量*/
    @Override
    public int getItemCount() {
        return (mListData == null || mListData.isEmpty()) ? 0 : mListData.size();
    }

    /*设置点击事件*/
    public void setOnItemClickListener(OnItemClickListener onClickListener) {
        this.mClickListener = onClickListener;
    }

    public interface OnItemClickListener {
        /*点击事件*/
        void OnItemClick(View view, int position);

        /*长按点击事件*/
        void OnItemLongClick(View view, int position);
    }
}

ViewHolder
这里提供了两种设置控件的方法:
(int , String)适用于最基本的显示;
(int,String,CallBack)适用于稍复杂的控件显示,如控件有点击事件。。。。;

public class BaseRecyclerViewHolder extends RecyclerView.ViewHolder {
    private View inflate;
    private Context mContext;

    public BaseRecyclerViewHolder(View itemView, Context context) {
        super(itemView);
        this.inflate = itemView;
        this.mContext = context;
    }

    /*设置TextView 控件*/
    public void setText(int tvID, String text, CallBack<TextView> callBack) {
        TextView tx = (TextView) inflate.findViewById(tvID);
        tx.setText(text);
        if (callBack != null) {
            callBack.run(tx);
        }
    }

    /*设置ImageView 控件*/
    public void setImageResource(int ivID, int resouceId, CallBack<ImageView> callBack) {
        ImageView img = (ImageView) inflate.findViewById(ivID);
        img.setImageResource(resouceId);
        if (callBack != null) {
            callBack.run(img);
        }
    }

    /*设置CheckBox 控件*/
    public void setCheckBox(int cbID, boolean cb, CallBack<CheckBox> callBack) {
        CheckBox cbox = (CheckBox) inflate.findViewById(cbID);
        cbox.setChecked(cb);
        if (callBack != null) {
            callBack.run(cbox);
        }
    }

    /*设置ImageButton 控件*/
    public void setImageButton(int ibtnID, CallBack<ImageButton> callBack) {
        ImageButton ibtn = (ImageButton) inflate.findViewById(ibtnID);
        if (callBack != null) {
            callBack.run(ibtn);
        }
    }

    /*设置LinearLayout 控件*/
    public void setLinearLayout(int layoutID, CallBack<LinearLayout> callBack) {
        LinearLayout layout = (LinearLayout) inflate.findViewById(layoutID);
        if (callBack != null) {
            callBack.run(layout);
        }
    }

    /*设置RelativeLayout 控件*/
    public void setRelativeLayout(int layoutID, CallBack<RelativeLayout> callBack) {
        RelativeLayout layout = (RelativeLayout) inflate.findViewById(layoutID);
        if (callBack != null) {
            callBack.run(layout);
        }
    }

    /*设置GridView 控件*/
    public void setGridView(int gridID, CallBack<GridView> callBack) {
        GridView grid = (GridView) inflate.findViewById(gridID);
        if (callBack != null) {
            callBack.run(grid);
        }
    }

    /*回调函数*/
    public interface CallBack<T> {
        void run(T t);
    }
}

此处回调函数CallBack做了调整, 之前使用时需要转换类型才可以使用, 添加了泛型之后可以不用再转换类型
分割线
这里的分割线可以适用于部分RecycleView ,有些需要进行微调

public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {
    private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
    private Drawable mDivider;

    public DividerGridItemDecoration(Context context) {
        final TypedArray a = context.obtainStyledAttributes(ATTRS);
        mDivider = a.getDrawable(0);
        a.recycle();
    }

    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        /*绘画横向间隔  — */
        drawHorizontal(c, parent);
        /*绘画纵向间隔  | */
        drawVertical(c, parent);
    }

    private int getSpanCount(RecyclerView parent) {
        /*获取RecycleView 的列数*/
        int spanCount = -1;
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            spanCount = ((StaggeredGridLayoutManager) layoutManager).getSpanCount();
        }
        return spanCount;
    }

    public void drawHorizontal(Canvas canvas, RecyclerView parent) {
        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.getLeft() - params.leftMargin;
            final int right = child.getRight() + params.rightMargin + mDivider.getIntrinsicWidth();
            final int top = child.getBottom() + params.bottomMargin;
            final int bottom = top + mDivider.getIntrinsicHeight();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(canvas);
        }
    }

    public void drawVertical(Canvas canvas, RecyclerView parent) {
        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 top = child.getTop() - params.topMargin;
            final int bottom = child.getBottom() + params.bottomMargin;
            final int left = child.getRight() + params.rightMargin;
            final int right = left + mDivider.getIntrinsicWidth();

            mDivider.setBounds(left, top, right, bottom);
            mDivider.draw(canvas);
        }
    }

    /*判断是否是最后一列*/
    private boolean isLastColum(RecyclerView parent, int pos, int spanCount, int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            if ((pos + 1) % spanCount == 0) {
                // 如果是最后一列,则不需要绘制右边
                return true;
            }
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                if ((pos + 1) % spanCount == 0) {
                    // 如果是最后一列,则不需要绘制右边
                    return true;
                }
            } else {
                childCount = childCount - childCount % spanCount;
                if (pos >= childCount)
                    // 如果是最后一列,则不需要绘制右边
                    return true;
            }
        }
        return false;
    }

    /*判断是否是最后一行*/
    private boolean isLastRaw(RecyclerView parent, int pos, int spanCount, int childCount) {
        RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            childCount = childCount - childCount % spanCount;
            if (pos >= childCount) // 如果是最后一行,则不需要绘制底部
                return true;
        } else if (layoutManager instanceof StaggeredGridLayoutManager) {
            int orientation = ((StaggeredGridLayoutManager) layoutManager)
                    .getOrientation();
            // StaggeredGridLayoutManager 且纵向滚动
            if (orientation == StaggeredGridLayoutManager.VERTICAL) {
                childCount = childCount - childCount % spanCount;
                // 如果是最后一行,则不需要绘制底部
                if (pos >= childCount)
                    return true;
            } else {
                // StaggeredGridLayoutManager 且横向滚动
                // 如果是最后一行,则不需要绘制底部
                if ((pos + 1) % spanCount == 0) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void getItemOffsets(Rect outRect, int itemPosition,
                               RecyclerView parent) {
        int spanCount = getSpanCount(parent);
        int childCount = parent.getAdapter().getItemCount();
        int intrinsicWidth = mDivider.getIntrinsicWidth();
        int intrinsicHeight = mDivider.getIntrinsicHeight();
        if (isLastRaw(parent, itemPosition, spanCount, childCount)) {
            // 如果是最后一行,则不需要绘制底部
            outRect.set(0, 0, intrinsicWidth, 0);
        } else if (isLastColum(parent, itemPosition, spanCount, childCount)) {
            // 如果是最后一列,则不需要绘制右边
            outRect.set(0, 0, 0, intrinsicHeight);
        } else {
            outRect.set(0, 0, intrinsicWidth,
                    intrinsicHeight);
        }
    }
}

使用
MainActivity.class

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecycleView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_main);
        /*初始化空间*/
        mRecycleView = (RecyclerView) findViewById(R.id.recycle);
        /*设置布局管理器 */
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 2);
        gridLayoutManager.setOrientation(GridLayoutManager.VERTICAL);
        mRecycleView.setLayoutManager(gridLayoutManager);
//        mRecycleView.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.HORIZONTAL));
//        mRecycleView.setLayoutManager(new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL));

        /*设置分割线*/
        mRecycleView.addItemDecoration(new DividerGridItemDecoration(this));

        /*初始化数据*/
        List<MyBean> list = new ArrayList<>();
        for (int i = 0; i < 20000; i++) {
            MyBean myBean = new MyBean();
            myBean.setName("这是第" + (i + 1) + "条数据");
            list.add(myBean);
        }
        /*设置适配器*/
        RecycleAdapterTest adapter = new RecycleAdapterTest(this);
        adapter.setData(list);
        mRecycleView.setAdapter(adapter);
        /*设置操作动画*/
        mRecycleView.setItemAnimator(new DefaultItemAnimator());
        /*设置点击事件*/
        adapter.setOnItemClickListener(new BaseRecyclerViewAdapter.OnItemClickListener() {
            @Override
            public void OnItemClick(View view, int position) {
                Toast.makeText(MainActivity.this, "=============>>>点击" + position, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void OnItemLongClick(View view, int position) {
                Toast.makeText(MainActivity.this, "长点击======>>>" + position, Toast.LENGTH_SHORT).show();
            }
        });
    }

}

MyBean

public class MyBean{
    private String name;
    private String np;
    private int iv;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getIv() {
        return iv;
    }

    public void setIv(int iv) {
        this.iv = iv;
    }

    public String getNp() {
        return np;
    }

    public void setNp(String np) {
        this.np = np;
    }
}

适配器使用 RecycleAdapterTest
这里的图片的点击事件会抢夺 BaseRecyclerViewAdapter中的图片区域的焦点

public class RecycleAdapterTest extends BaseRecyclerViewAdapter<MyBean> {
    int[] imgs = {R.mipmap.p1, R.mipmap.p2, R.mipmap.p3, R.mipmap.p4, R.mipmap.p5, R.mipmap.p6,};

    public RecycleAdapterTest(Context mContext) {
        super(R.layout.home_masonry_item, mContext);
    }

    @Override
    protected void convert(BaseRecyclerViewHolder holder, MyBean bean, int position) {
        MyBean p = bean;

        /*文字部分只作为显示*/
        holder.setText(R.id.masonry_item_title, p.getName(),null);

        /*图片部分设置点击事件*/
        holder.setImageResource(R.id.masonry_item_img, imgs[position % 6], new BaseRecyclerViewHolder.CallBack<ImageView>() {
            @Override
            public void run(ImageView imageView) {
                imageView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(v.getContext(), "这是点击", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

}

* layout_main 布局*

<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.v7.widget.RecyclerView
        android:id="@+id/recycle"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

home_masonry_item.xml 布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#fff">

    <ImageView
        android:src="@mipmap/p1"
        android:id="@+id/masonry_item_img"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="centerCrop"/>
    <TextView
        android:text="文字部分"
        android:id="@+id/masonry_item_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"/>
</LinearLayout>

RecycleView Adapter封装使用
* divider.xml *
分割线的样式style

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <gradient
        android:centerColor="#ff00ff00"
        android:endColor="#ff0000ff"
        android:startColor="#ffff0000"
        android:type="linear" />
    <size android:height="5dp" android:width="5dp"/>
</shape>

RecycleView Adapter封装使用
运行结果
RecycleView Adapter封装使用

改成流式布局之后
RecycleView Adapter封装使用

相关标签: adapter RecycleView