RecyclerView is very popular now, right? RecyclerView is naturally a very convenient control, but sometimes with more repeatable code is also feel very troublesome, so I will be some repeatable code encapsulated, so that the use of RecyclerView is more convenient

This blog includes:

  • Universal single layout RecyclerView.Adapter
  • Universal multi-layout RecyclerView.Adapter
  • Gm’s RecyclerView ItemDecoration
  • RecyclerView click and long press events listening
  • Lead section with bottom View RecyclerView
  • The use of SnapHelper

RecyclerView.Adapter

CommonRecyclerViewAdapter is an abstract class, the use of generic construct a universal Adapter, and through the MultiTypeSupport interface to implement the support for multiple layout. In addition, sometimes, when we refresh data change in data collection may be just a List, a single data, if use the Adapter. The notifyDataSetChanged () to refresh the view, no doubt is a waste of resources, DiffUtil is adopted here to contrast before and after the two data sets, Find out the minimum change of the old data set and the new data set, so as to carry out directional refresh of data. Only the corresponding Item can be refreshed, making the view refresh process more efficient, and the addition and deletion of data are accompanied by corresponding animation effect

/** * Author: Ye Should be ye * time: 2017/12/21 21:50 *
public abstract class CommonRecyclerViewAdapter<T> extends RecyclerView.Adapter<CommonRecyclerViewHolder> {

    // Omit some code.private DiffUtil.Callback callback = new DiffUtil.Callback() {

        @Override
        public int getOldListSize(a) {
            return getItemCount();
        }

        @Override
        public int getNewListSize(a) {
            return newDataList.size();
        }

        @Override
        public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
            return CommonRecyclerViewAdapter.this.areItemsTheSame(oldItemPosition, newItemPosition);
        }

        @Override
        public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
            return CommonRecyclerViewAdapter.this.areContentsTheSame(oldItemPosition, newItemPosition);
        }

        @Nullable
        @Override
        public Object getChangePayload(int oldItemPosition, int newItemPosition) {
            return CommonRecyclerViewAdapter.this.getChangePayload(oldItemPosition, newItemPosition); }};public void setData(final List<T> dataList) {
        new Thread(new Runnable() {
            @Override
            public void run(a) {
                newDataList.clear();
                newDataList = CommonRecyclerViewAdapter.this.clone(dataList);
                DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback, true);
                Message message = new Message();
                message.what = DIFF_UTIL_UPDATE;
                message.obj = diffResult;
                handler.sendMessage(message);
            }
        }).start();
    }

    @Override
    public int getItemViewType(int position) {
        if(multiTypeSupport ! =null) {
            return multiTypeSupport.getLayoutId(dataList.get(position), position);
        }
        return DEFAULT_ITEM_VIEW_TYPE;
    }

    @Override
    public CommonRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(multiTypeSupport ! =null) {
            layoutId = viewType;
        }
        return new CommonRecyclerViewHolder(layoutInflater.inflate(layoutId, parent, false));
    }

    @Override
    public void onBindViewHolder(CommonRecyclerViewHolder holder, int position, List<Object> payloads) {
        if (payloads.isEmpty()) {
            onBindViewHolder(holder, position);
        } else {
            Bundle bundle = (Bundle) payloads.get(0); partialBindData(holder, bundle); }}@Override
    public void onBindViewHolder(CommonRecyclerViewHolder holder, int position) {
        entirelyBindData(holder, dataList.get(position));
        if(clickListener ! =null) {
            holder.setClickListener(clickListener);
        }
        if(longClickListener ! =null) { holder.setLongClickListener(longClickListener); }}// Omit some code.private List<T> clone(List<T> dataList) {
        List<T> tempDataList = new ArrayList<>(dataList.size());
        for (T data : dataList) {
            tempDataList.add(clone(data));
        }
        return tempDataList;
    }

    /** * clone the specified object to get a copy of it **@paramData The object to copy *@returnObject copy */
    protected abstract T clone(T data);

    /** * Check whether the specified index position points to the same data before and after the refresh of the data list **@paramOldItemPosition Data index before update *@paramNewItemPosition Updated data index *@returnWhether to point to the same data */
    protected abstract boolean areItemsTheSame(int oldItemPosition, int newItemPosition);

    /** * this method is called only if areItemsTheSame returns true@paramOldItemPosition Data index before update *@paramNewItemPosition Updated data index *@returnWhether the data content has changed */
    protected abstract boolean areContentsTheSame(int oldItemPosition, int newItemPosition);

    This method is called only if areContentsTheSame returns false@paramOldItemPosition Data index before update *@paramNewItemPosition Updated data index *@returnData change content */
    @NonNull
    protected abstract Bundle getChangePayload(int oldItemPosition, int newItemPosition);

    /** * Only update views where the data has changed@param holder Holder
     * @paramThe return value of the bundle getChangePayload method */
    protected abstract void partialBindData(CommonRecyclerViewHolder holder, @NonNull Bundle bundle);

    /** * Fully bind data **@param holder Holder
     * @param data   Data
     */
    protected abstract void entirelyBindData(CommonRecyclerViewHolder holder, T data);

}
Copy the code

A universal recyclerView.viewholder is also needed

/** * 作者 : ye should be ye * time: 2017/12/21 21:52 *
public class CommonRecyclerViewHolder extends RecyclerView.ViewHolder {

    public interface OnClickListener {
        void onClick(int position);
    }

    public interface OnLongClickListener {
        void onLongClick(int position);
    }

    private OnClickListener clickListener;

    private OnLongClickListener longClickListener;

    // Hold views to reduce findViewById count
    private SparseArray<View> viewSparseArray;

    CommonRecyclerViewHolder(View view) {
        super(view);
        viewSparseArray = new SparseArray<>();
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(clickListener ! =null) { clickListener.onClick(getAdapterPosition()); }}}); view.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if(longClickListener ! =null) {
                    longClickListener.onLongClick(getAdapterPosition());
                }
                return true; }}); }void setClickListener(OnClickListener clickListener) {
        this.clickListener = clickListener;
    }

    void setLongClickListener(OnLongClickListener longClickListener) {
        this.longClickListener = longClickListener;
    }

    /** * Get View ** by ID@param viewId viewID
     * @param< T > generic *@returnForce the result to View or a View subtype */
    private <T extends View> T getView(@IdRes int viewId) {
        // Search the cache first, if found, return directly
        // If it can't find findViewById, store the result in the cache
        View view = viewSparseArray.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            if(view ! =null) { viewSparseArray.put(viewId, view); }}return (T) view;
    }

    public CommonRecyclerViewHolder setText(@IdRes int viewId, CharSequence text) {
        TextView textView = getView(viewId);
        if(textView ! =null) {
            textView.setText(text);
        }
        return this;
    }

	// Omit some code. }Copy the code

2. Examples of common single layout Adapter

Let’s create a new Model

/** * Author: Ye Ying Shi Ye * Time: 2017/12/21 21:55 * Description: */
public class New {

    private int index;

    private String title;

    private String content;

    public New(int index, String title, String content) {
        this.index = index;
        this.title = title;
        this.content = content;
    }

    // Omit some code. }Copy the code

The layout of each subitem consists of an index TextView, a title TextView, and a content TextView


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

    <TextView
        android:id="@+id/tv_index"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:padding="6dp"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:padding="5dp"
        android:textSize="28sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="start"
        android:padding="10dp"
        android:textSize="22sp" />

</LinearLayout>
Copy the code

Followed by inheriting CommonRecyclerViewAdapter, generic specified as the New, specified directly in the constructor to use layout for R.l ayout. Item_new, realize several abstract method again can.

/** * Author: Ye Ying Is ye * Time: 2017/12/21 21:55 * Description: Single layout */
public class NewCommonAdapter extends CommonRecyclerViewAdapter<New> {

    public NewCommonAdapter(Context context, List<New> dataList) {
        super(context, dataList, R.layout.item_new);
    }

    @Override
    protected New clone(New data) {
        return new New(data.getIndex(), data.getTitle(), data.getContent());
    }

    @Override
    protected boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        return dataList.get(oldItemPosition).getIndex() == newDataList.get(newItemPosition).getIndex();
    }

    @Override
    protected boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        String title = dataList.get(oldItemPosition).getTitle();
        String content = dataList.get(oldItemPosition).getContent();
        String newTitle = newDataList.get(newItemPosition).getTitle();
        String newContent = newDataList.get(newItemPosition).getContent();
        return title.equals(newTitle) && content.equals(newContent);
    }

    @NonNull
    @Override
    protected Bundle getChangePayload(int oldItemPosition, int newItemPosition) {
        Bundle bundle = new Bundle();
        String title = dataList.get(oldItemPosition).getTitle();
        String content = dataList.get(oldItemPosition).getContent();
        String newTitle = newDataList.get(newItemPosition).getTitle();
        String newContent = newDataList.get(newItemPosition).getContent();
        if(! title.equals(newTitle)) { bundle.putString("Title", newTitle);
        }
        if(! content.equals(newContent)) { bundle.putString("Content", newContent);
        }
        return bundle;
    }

    @Override
    protected void partialBindData(CommonRecyclerViewHolder holder, @NonNull Bundle bundle) {
        for (String key : bundle.keySet()) {
            switch (key) {
                case "Title":
                    holder.setText(R.id.tv_title, bundle.getString(key));
                    break;
                case "Content":
                    holder.setText(R.id.tv_content, bundle.getString(key));
                    break; }}}@Override
    protected void entirelyBindData(CommonRecyclerViewHolder holder, New data) { holder.setText(R.id.tv_title, data.getTitle()) .setText(R.id.tv_content, data.getContent()); }}Copy the code

Here omit all kinds of initialization operations of RecyclerView in the Activity, only show the final effect, see the specific code at the bottom of GitHub address

Use examples of universal multi-layout Adapter

Among CommonRecyclerViewAdapter class, in order to support multiple layout, through MultiTypeSupport interface to return the corresponding layout file ID, here in addition to using single layout used in R.l ayout. Item_new layout file, Use another layout file, r.layout.item_new_multi, just with a different background color

Want to let the child Adapter supports multiple layout, as long as achieve CommonRecyclerViewAdapter another constructor. Here the r.layout.item_new layout is used for singular indexes and the R.layout.item_new_multi layout is used for even indexes

/** * Author: Ye Ying Is ye * Time: 2017/12/21 21:56 * Description: Multiple layout */
public class NewCommonMultiAdapter extends CommonRecyclerViewAdapter<New> {

    public NewCommonMultiAdapter(Context context, List<New> dataList) {
        super(context, dataList, new CommonRecyclerViewAdapter.MultiTypeSupport<New>() {
            @Override
            public int getLayoutId(New item, int position) {
                return item.getIndex() % 2= =0? R.layout.item_new_multi : R.layout.item_new; }}); }// Omit some code.@Override
    protected void partialBindData(CommonRecyclerViewHolder holder, @NonNull Bundle bundle) {
        if (bundle.size() > 0) {
            int index = bundle.getInt("Index");
            for (String key : bundle.keySet()) {
                switch (key) {
                    case "Title":
                        if (index % 2= =0) {
                            holder.setText(R.id.tv_multi_title, bundle.getString(key));
                        } else {
                            holder.setText(R.id.tv_title, bundle.getString(key));
                        }
                        break;
                    case "Content":
                        if (index % 2= =0) {
                            holder.setText(R.id.tv_multi_content, bundle.getString(key));
                        } else {
                            holder.setText(R.id.tv_content, bundle.getString(key));
                        }
                        break; }}}}@Override
    protected void entirelyBindData(CommonRecyclerViewHolder holder, New data) {
        if (data.getIndex() % 2= =0) {
            holder.setText(R.id.tv_multi_title, data.getTitle())
                    .setText(R.id.tv_multi_content, data.getContent())
                    .setText(R.id.tv_multi_index, String.valueOf(data.getIndex()));
        } else{ holder.setText(R.id.tv_title, data.getTitle()) .setText(R.id.tv_content, data.getContent()) .setText(R.id.tv_index, String.valueOf(data.getIndex())); }}}Copy the code

Add header and bottom View

In order to realize the RecyclerView of the head and bottom View, we need to define a custom Adapter to wrap the actual Adapter, rewrite the getItemViewType(int Position) method, return different values to distinguish the head View from the bottom View, And open up ways to add and remove views from the bottom of the header

Note: You can add the head View and bottom View of the RecyclerView Adapter */
public class WrapRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private RecyclerView.Adapter<RecyclerView.ViewHolder> innerAdapter;

    private SparseArray<View> headerViewArray;

    private SparseArray<View> footerViewArray;

    // The header position of the View type, used for the viewType
    private static int BASE_VIEW_TYPE_HEADER = 1000;

    // Bottom View type start position, for viewType
    private static int BASE_VIEW_TYPE_FOOTER = 2000;

    private RecyclerView.AdapterDataObserver dataObserver = new RecyclerView.AdapterDataObserver() {

        @Override
        public void onChanged(a) {
            super.onChanged();
            notifyDataSetChanged();
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            super.onItemRangeChanged(positionStart, itemCount);
            notifyItemRangeChanged(positionStart + getHeaderViewCount(), itemCount);
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
            notifyItemRangeInserted(positionStart + getHeaderViewCount(), itemCount);
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            super.onItemRangeRemoved(positionStart, itemCount);
            notifyItemRangeRemoved(positionStart + getHeaderViewCount(), itemCount);
        }

        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            super.onItemRangeMoved(fromPosition, toPosition, itemCount);
            intheaderViewsCountCount = getHeaderViewCount(); notifyItemRangeChanged(fromPosition + headerViewsCountCount, toPosition + headerViewsCountCount + itemCount); }};public WrapRecyclerViewAdapter(RecyclerView.Adapter innerAdapter) {
        headerViewArray = new SparseArray<>();
        footerViewArray = new SparseArray<>();
        setAdapter(innerAdapter);
    }

    private void setAdapter(RecyclerView.Adapter<RecyclerView.ViewHolder> adapter) {
        innerAdapter = adapter;
        innerAdapter.registerAdapterDataObserver(dataObserver);
    }

    @Override
    public int getItemViewType(int position) {
        if (isHeaderPosition(position)) {
            return headerViewArray.keyAt(position);
        }
        if (isFooterPosition(position)) {
            return footerViewArray.keyAt(position - headerViewArray.size() - getDataItemCount());
        }
        return innerAdapter.getItemViewType(position - headerViewArray.size());
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (isHeaderView(viewType)) {
            return new ViewHolder(headerViewArray.get(viewType));
        }
        if (isFooterView(viewType)) {
            return new ViewHolder(footerViewArray.get(viewType));
        }
        return innerAdapter.onCreateViewHolder(parent, viewType);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        int headerViewsCountCount = getHeaderViewCount();
        if(position >= headerViewsCountCount && position < headerViewsCountCount + innerAdapter.getItemCount()) { innerAdapter.onBindViewHolder(holder, position - headerViewsCountCount); }}@Override
    public int getItemCount(a) {
        return getHeaderViewCount() + getDataItemCount() + getFooterViewCount();
    }

    private int getDataItemCount(a) {
        return innerAdapter == null ? 0 : innerAdapter.getItemCount();
    }

    public int getHeaderViewCount(a) {
        return headerViewArray.size();
    }

    public int getFooterViewCount(a) {
        return footerViewArray.size();
    }

    public RecyclerView.Adapter getInnerAdapter(a) {
        return innerAdapter;
    }

    /** * check whether it is a header View **@param viewType ViewType
     * @returnIs the header View */
    private boolean isHeaderView(int viewType) {
        return headerViewArray.indexOfKey(viewType) > -1;
    }

    /** * check if it is bottom View **@param viewType ViewType
     * @returnIs it bottom View */
    private boolean isFooterView(int viewType) {
        return footerViewArray.indexOfKey(viewType) > -1;
    }

    /** * check whether it is a header View **@param view View
     * @returnIs the header View */
    public boolean isHeaderView(View view) {
        return headerViewArray.indexOfValue(view) > -1;
    }

    /** * check if it is bottom View **@param view View
     * @returnIs it bottom View */
    public boolean isFooterView(View view) {
        return footerViewArray.indexOfValue(view) > -1;
    }

    /** * Check whether the View at the position is a header View **@paramThe position index *@returnIs the header View */
    private boolean isHeaderPosition(int position) {
        return position >= 0 && position < getHeaderViewCount();
    }

    /** * Check whether the View at this position is the bottom View **@paramThe position index *@returnIs it bottom View */
    private boolean isFooterPosition(int position) {
        return position >= (getHeaderViewCount() + getDataItemCount())
                && position < (getHeaderViewCount() + getDataItemCount() + getFooterViewCount());
    }

    /** * Add header View **@paramView header view */
    public void addHeaderView(View view) {
        if (headerViewArray.indexOfValue(view) < 0) {
            headerViewArray.put(BASE_VIEW_TYPE_HEADER++, view);
            notifyItemInserted(headerViewArray.size() - 1); }}/** * Add bottom View **@paramView bottom view */
    public void addFooterView(View view) {
        if (footerViewArray.indexOfValue(view) < 0) {
            footerViewArray.put(BASE_VIEW_TYPE_FOOTER++, view);
            notifyItemInserted(getHeaderViewCount() + getDataItemCount() + getFooterViewCount() - 1); }}/** * Remove the header View **@param view View
     */
    public void removeHeaderView(View view) {
        int index = headerViewArray.indexOfValue(view);
        if (index > -1) { headerViewArray.removeAt(index); notifyItemRemoved(index); }}/** * Remove bottom View **@param view View
     */
    public void removeFooterView(View view) {
        int index = footerViewArray.indexOfValue(view);
        if (index > -1) { footerViewArray.removeAt(index); notifyItemRemoved(getHeaderViewCount() + getDataItemCount() + index); }}private class ViewHolder extends RecyclerView.ViewHolder {

        ViewHolder(View itemView) {
            super(itemView); }}}Copy the code

The use of WrapRecyclerViewAdapter is also very simple, as long as the actual Adapter as a parameter to construct WrapRecyclerViewAdapter object, and then pass to RecyclerView can, You can then add the header and bottom views using the addHeaderView and addFooterView methods

        RecyclerView rv_wrapDataList = (RecyclerView) findViewById(R.id.rv_wrapDataList);
        NewCommonAdapter adapter = new NewCommonAdapter(this, newList);
        WrapRecyclerViewAdapter wrapRecyclerViewAdapter = new WrapRecyclerViewAdapter(adapter);
        rv_wrapDataList.setLayoutManager(new LinearLayoutManager(this));
        rv_wrapDataList.setAdapter(wrapRecyclerViewAdapter);
Copy the code

5. Click and hold events

RecyclerView click and long press event has always been a tricky place, after all, there is no official provided interfaces, but here CommonRecyclerViewAdapter has also provides the corresponding setting method

        NewCommonMultiAdapter newCommonMultiAdapter = new NewCommonMultiAdapter(this, newList);
        newCommonMultiAdapter.setClickListener(new CommonRecyclerViewHolder.OnClickListener() {
            @Override
            public void onClick(int position) {
                toast("Click" + "\n" + newList.get(position).getTitle() + "\n"+ newList.get(position).getContent()); }}); newCommonMultiAdapter.setLongClickListener(new CommonRecyclerViewHolder.OnLongClickListener() {
            @Override
            public void onLongClick(int position) {
                toast("Long press" + "\n" + newList.get(position).getTitle() + "\n"+ newList.get(position).getContent()); }});Copy the code

Six, general RecyclerView ItemDecoration

Want to make the line between the Item, we need to inherit RecyclerView. ItemDecoration to paint in the corresponding position, here to provide a general dividing line

/** * Author: Ye Ying Ye * Time: 2017/12/21 21:52 * Description: Universal divider */
public class CommonItemDecoration extends RecyclerView.ItemDecoration{

    private int orientation = LinearLayoutManager.HORIZONTAL;

    private Drawable drawable;

    public CommonItemDecoration(Context context, int orientation) {
        this.orientation = orientation;
        int[] attrs = new int[]{android.R.attr.listDivider};
        TypedArray typedArray = context.obtainStyledAttributes(attrs);
        drawable = typedArray.getDrawable(0);
        typedArray.recycle();
    }

    public CommonItemDecoration(Drawable drawable, int orientation) {
        this.drawable = drawable;
        this.orientation = orientation;
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);
        if (orientation == LinearLayoutManager.HORIZONTAL) {
            outRect.set(0.0, drawable.getIntrinsicWidth(), 0);
        } else if (orientation == LinearLayoutManager.VERTICAL) {
            outRect.set(0.0.0, drawable.getIntrinsicHeight()); }}@Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        super.onDraw(c, parent, state);
        if (orientation == LinearLayoutManager.HORIZONTAL) {
            drawVerticalDivider(c, parent);
        } else if(orientation == LinearLayoutManager.VERTICAL) { drawHorizontalDivider(c, parent); }}private void drawVerticalDivider(Canvas c, RecyclerView parent) {
        for (int i = 0; i < parent.getChildCount(); i++) {
            View child = parent.getChildAt(i);
// RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
// // is affected by the child layout_marginEnd attribute
// int left = child.getRight() + params.rightMargin;
            // Is not affected by the child layout_marginEnd property and is drawn directly to the right of the child
            int left = child.getRight();
            int top = child.getTop();
            int right = left + drawable.getIntrinsicWidth();
            intbottom = child.getBottom(); drawable.setBounds(left, top, right, bottom); drawable.draw(c); }}private void drawHorizontalDivider(Canvas c, RecyclerView parent) {
        for (int i = 0; i < parent.getChildCount(); i++) {
            View child = parent.getChildAt(i);
            int left = child.getLeft();
            // Not affected by the child layout_marginBottom property, will be drawn directly at the bottom of the child
            int top = child.getBottom();
            int right = child.getRight();
            int bottom = top + drawable.getIntrinsicHeight();
            // Is affected by the child layout_marginBottom attribute
            //RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            //int top = child.getBottom() + params.bottomMargin;drawable.setBounds(left, top, right, bottom); drawable.draw(c); }}}Copy the code

In the previous several renderings, in fact, has been added a white separation line for RecyclerView

RecyclerView rv_commonMultiDataList = (RecyclerView) findViewById(R.id.rv_commonMultiDataList);
CommonItemDecoration commonItemDecoration = new CommonItemDecoration(ContextCompat.getDrawable(this, R.drawable.divider), LinearLayoutManager.VERTICAL);
        rv_commonMultiDataList.addItemDecoration(commonItemDecoration);
Copy the code

It is also possible to pass in different Drawable objects to implement multiple styles of delimiters

Use SnapHelper

By the way, here is a simple introduction to SnapHelper. SnapHelper is a new support library added in the Support package of Android 24.2.0, which is an extension of RecyclerView. SnapHelper aims to support the alignment of RecyclerView. By calculating the alignment of the specified point of TargetView in RecyclerView or any pixel point in the container, RecyclerView can achieve the switching effect similar to ViewPager

SnapHelper is an abstract class which provides two concrete implementations of LinearSnapHelper and PagerSnapHelper, which is similar to the boot page displayed when using the App for the first time

/** * Author: Ye Ying Shi Ye * Time: 2017/12/21 22:02 * Description: */
public class SnapRecyclerViewActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_snap_recycler_view);
        RecyclerView rv_snap = (RecyclerView) findViewById(R.id.rv_snap);
        SnapAdapter snapAdapter = new SnapAdapter(this, getData());
        rv_snap.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
// rv_snap.setLayoutManager(new LinearLayoutManager(this));
        rv_snap.setAdapter(snapAdapter);
// LinearSnapHelper snapHelper = new LinearSnapHelper();
// snapHelper.attachToRecyclerView(rv_snap);
        PagerSnapHelper pagerSnapHelper=new PagerSnapHelper();
        pagerSnapHelper.attachToRecyclerView(rv_snap);
    }

    private List<Image> getData(a) {
        List<Image> imageList = new ArrayList<>();
        imageList.add(new Image(0, R.drawable.drawable_1));
        imageList.add(new Image(1, R.drawable.drawable_0));
        imageList.add(new Image(2, R.drawable.drawable_1));
        imageList.add(new Image(3, R.drawable.drawable_0));
        imageList.add(new Image(4, R.drawable.drawable_1));
        imageList.add(new Image(5, R.drawable.drawable_0));
        imageList.add(new Image(6, R.drawable.drawable_1));
        imageList.add(new Image(7, R.drawable.drawable_0));
        returnimageList; }}Copy the code

Source code I have also put on GitHub, click to see: Android RecyclerView simple to write