### introduction of RecycleView
RecyclerView is a new view group that aims to provide similar rendering for any adapter-based view. This control is used to display large data sets in a limited window as a successor to the ListView and GridView controls.
So with ListView, GridView why also need RecyclerView controls like it? As a whole, RecyclerView architecture provides a plug-and-pull experience with a high degree of decoupling and exceptional flexibility. By setting different LayoutManager, ItemDecoration and ItemAnimator it provides, stunning effects can be achieved.
- If you want to control how it is displayed, use the LayoutManager, LayoutManager
- If you want to control the spacing between items (graphable), go through ItemDecoration
- If you want to animate an Item, use the ItemAnimator
- If you want to control the click and hold events, write them yourself.
2. The basic use of RecycleView
1. Create a RecycleView dependency library in Gradle.
The compile 'com. Android. Support: recyclerview - v7:23.1.1'Copy the code
2, place our RecycleView in the layout file.
<? The XML version = "1.0" encoding = "utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recycle" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>Copy the code
3, create Adapter class inherit Adapter RecycleView, the steps are:
- Recyclerview. ViewHolder class recyclerView. ViewHolder class, and then throw your own ViewHolder class into the generic Adapter class.
- The layout of the control can be found by ID in the constructor of the custom ViewHolder class. The control needs to be declared as a member variable of the custom ViewHolder class.
- Create a custom ViewHolder class object. Create a custom ViewHolder class object. Create a custom ViewHolder class object and create a custom ViewHolder class object. The onBindViewHolder is responsible for setting data into the Item control. GetItemCount is mainly responsible for getting the number of data.
- It is better to declare the data as member variables and pass it in the constructor.
- Because RecycleView native does not support click events, need to add their own interface for callback.
The code is as follows:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> { List<String> mDatas = null; Context mContext = null; Public MyAdapter(List<String> mDatas, Context Context) {this.mdatas = mDatas; this.mContext = context; } @override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // View v = View.inflate(mContext, R.layout.item, null); LayoutInflater inflater = LayoutInflater.from(mContext); // View v = inflater.inflate(r.layout.layout_item, parent, false); MyViewHolder holder = new MyViewHolder(v); return holder; } @override public void onBindViewHolder(MyViewHolder holder, MyViewHolder holder, MyViewHolder holder) int position) { holder.tv_num.setText(mDatas.get(position)); } @Override public int getItemCount() { return mDatas.size(); } // The custom ViewHolder must inherit recyclerView.viewholder. Class MyViewHolder extends recyclerView. ViewHolder {TextView tv_num; public MyViewHolder(final View itemView) { super(itemView); tv_num = (TextView) itemView.findViewById(R.id.tv_num); tv_num.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (onItemClickListener ! = null) { onItemClickListener.onItemClick(itemView, getLayoutPosition(), mDatas.get(getLayoutPosition())); }}}); }} private OnItemClickListener OnItemClickListener; public void setOnItemClickListener(OnItemClickListener listener) { this.onItemClickListener = listener; } public interface OnItemClickListener { void onItemClick(View v, int position, String data); } public void addData(int position, String data) { mDatas.add(position, data); notifyItemInserted(position); } public void removeData(int position) { mDatas.remove(position); notifyItemRemoved(position); }}Copy the code
4. Here’s what you need to do in MainActivity. The core steps (some in no particular order) are as follows:
- Find RecyclerView by ID.
- RecyclerView Setting Adapter.
- RecyclerView set layout managers, commonly used layout managers have LinearLayoutManager: linear layout, LayoutManager implementation classes, types include Vertical and HorizontalGridLayoutManager; Grid layout, inherited from LinearLayoutManager, implementation effect similar to GridView; StaggeredGridLayoutManager staggered grid layout, but also the implementation class LayoutManager, types include Vertical and Horizontal, and GridLayoutManager are similar, but is staggered grid, This is a grid view of varying width and height, similar to a waterfall flow.
- RecyclerView set data insert, delete when the animation effect, here use the default. The following url is making the above open source animation effects: https://github.com/gabrielemariotti/RecyclerViewItemAnimators
- RecyclerView to set the decorator between items, here also use GitHub to provide the decorator, the code will be given in the attachment.
The code is as follows:
public class MainActivity extends AppCompatActivity { List<String> datas = null; private RecyclerView recyclerView; private MyAdapter myAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); recyclerView = (RecyclerView) findViewById(R.id.recycle); MyAdapter = new myAdapter (datas, this); recyclerView.setAdapter(myAdapter); / / set the layout manager to render out the effect of different recyclerView setLayoutManager (new LinearLayoutManager (this)); / / insert, delete the data set of animation effects (here using the default animation) recyclerView. SetItemAnimator (new DefaultItemAnimator ()); / / set each Item between decoration (here set to separation line) recyclerView. AddItemDecoration (new DividerItemDecoration (this, DividerItemDecoration.VERTICAL_LIST)); // Set item listener, Need a custom interface myAdapter. SetOnItemClickListener (new myAdapter. OnItemClickListener () {@ Override public void onItemClick (View v, int position, String data) { Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show(); }}); } private void initData() { datas = new ArrayList<>(); for (int i = 0; i < 300; i++) { datas.add(i + ""); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_add: myAdapter.addData(0, "new data"); recyclerView.scrollToPosition(0); break; case R.id.action_delete: myAdapter.removeData(0); break; case R.id.action_gridview: recyclerView.setLayoutManager(new GridLayoutManager(this, 4)); break; case R.id.action_listview: recyclerView.setLayoutManager(new LinearLayoutManager(this)); break; case R.id.action_staggeredgridview: recyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL)); break; } return true; }}Copy the code
Third, the operation effect
The first picture above three, some specific animation effects need to experience.
NotifyDataSetChanged is deprecated and RecycleView is changed:
- NotifyDataSetChanged () abandoned
- notifyItemChanged(int position)
- notifyItemInserted(int position)
- notifyItemMoved(int fromPosition, int toPosition)
- NotifyItemRemoved (int position) // Range of items
- notifyItemRangeChanged(int positionStart, int itemCount)
- notifyItemRangeInserted(int positionStart, int itemCount)
- notifyItemRangeRemoved(int positionStart, int itemCount)
Note: You can implement many different entries through Adapter’s getViewType(int Position) method. You do this by removing the different Item layouts depending on the position, such as odd or even, or a particular value, and depending on the viewType argument. As shown below:
Iv. Attachments
DividerGridItemDecoration.java
package cniao5.com.rvdemo; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.LayoutManager; import android.support.v7.widget.RecyclerView.State; import android.support.v7.widget.StaggeredGridLayoutManager; import android.view.View; 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, State state) { drawHorizontal(c, parent); drawVertical(c, parent); } private int getSpanCount(RecyclerView parent) {// int getSpanCount = 1; 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 c, 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(c); } } public void drawVertical(Canvas c, 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(c); } } private boolean isLastColum(RecyclerView parent, int pos, int spanCount, int childCount) { LayoutManager layoutManager = parent.getLayoutManager(); If (layoutManager instanceof GridLayoutManager) {if ((pos + 1) % spanCount == 0)// If (pos + 1) % spanCount == 0) } } else if (layoutManager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutManager) .getOrientation(); If (" orientation = = StaggeredGridLayoutManager. VERTICAL) {if ((pos + 1) % spanCount = = 0) / / if it's the last column, Do not draw the right {return true; } } else { childCount = childCount - childCount % spanCount; If (pos >= childCount)// If it is the last column, return true; } } return false; } private boolean isLastRaw(RecyclerView parent, int pos, int spanCount, int childCount) { LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { childCount = childCount - childCount % spanCount; If (pos >= childCount)// If it is the last line, return true is not required; } else if (layoutManager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutManager) .getOrientation(); / / StaggeredGridLayoutManager and longitudinal rolling the if (orientation = = StaggeredGridLayoutManager. VERTICAL) {childCount = childCount - childCount % spanCount; If (pos >= childCount) return true; } else / / StaggeredGridLayoutManager and horizontal scroll {/ / if it is the last line, do not need to draw the bottom of the 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(); If (isLastRaw(parent, itemPosition, spanCount, childCount)) You don't need to draw the bottom {outRect. Set (0, 0, mDivider getIntrinsicWidth (), 0). } else if (parent (parent, itemPosition, spanCount, childCount)) Do not need to draw the right {outRect. Set (0, 0, 0, mDivider getIntrinsicHeight ()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight()); }}}Copy the code
DividerItemDecoration.java
package cniao5.com.rvdemo; /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; /** * This class is from the v7 samples of the Android SDK. It's not by me! * <p/> * See the license above for details. */ 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) { Log.v("recyclerview - itemdecoration", "onDraw()"); 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); android.support.v7.widget.RecyclerView v = new android.support.v7.widget.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); }}}Copy the code
MyItemDacoration.java
package cniao5.com.rvdemo; import android.graphics.Canvas; import android.graphics.Rect; import android.support.v7.widget.RecyclerView; import android.view.View; /** * Created by Ivan on 15/9/30. */ public class MyItemDacoration extends RecyclerView.ItemDecoration { @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); } @Override public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDrawOver(c, parent, state); } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); }}Copy the code
If you feel that my words are helpful to you, welcome to pay attention to my public number:
My group welcomes everyone to come in and discuss all kinds of technical and non-technical topics. If you are interested, please add my wechat huannan88 and I will take you into our group.