Android RecyclerView first experience: androidrecyclerview
I have heard of the RecyclerView component a long time ago, but I have been very busy and have no time to learn it. Taking advantage of the weekend, it took a day to learn RecyclerView.
Preparations
Create an Android project in Android Studio and add the following tools:
compile 'com.android.support:support-v4:25.2.0' compile 'com.android.support:appcompat-v7:25.2.0' compile 'com.android.support:recyclerview-v7:25.2.0' compile 'com.github.bumptech.glide:glide:3.7.0'
The first two tools are not mentioned. Basically every Android project will be used. The third is the tool to be added using RecyclerView. The last tool is an open-source image loading tool recommended by Google, it makes image loading smoother and easier to use.
Put some images in the drawable directory, and name these images in the form of "image [a-zA-Z0-9] *" (because reflection is used in the program to find all image resources starting with "image ).
Put "add.png" and "remove.png" in the drawable directory and other image resources for the top toolbar.
Basic usage
To use RecyclerView, follow these steps:
1. Define a RecyclerView component in the resource file;
2. Get the defined RecyclerView component in the Activity. The variable name is simply called view;
3. Set LayoutManager (layout) for the view );
4. Set an Adapter for the view );
5. Add ItemDecoration (separator, optional) to the view );
6. Set ItemAnimator for the view (animation, optional ).
The following defines a RecyclerView component in the resource file:
1 <android.support.v7.widget.RecyclerView2 android:layout_width="match_parent"3 android:layout_height="0dp"4 android:layout_weight="1"5 android:id="@+id/vert_view" />
Then you can obtain the RecyclerView component in the Activity:
1 RecyclerView view=(RecyclerView) findViewById(R.id.vert_view);
Other details are described below.
Adapter
The adapter used for RecyclerView must inherit from RecyclerView. adapter <T> class, and override the T onCreateViewHolder (final ViewGroup parent, int viewType), void onBindViewHolder (T holder, final int position), and int getItemCount () methods. The following is a custom Adapter:
1 public class ViewAdapter extends RecyclerView. adapter <ViewAdapter. viewHolder> {2 private Context context; 3 private List <Animal> datas; 4 private int layoutResId; 5 private int imageViewId; 6 private int textViewId; 7 private boolean isCenterCrop; 8 9 public ViewAdapter (Context c, List <Animal> list, int lri, int ivi, int tvi, boolean centerCrop) {10 context = c; 11 datas = list; 12 layoutResId = lri; 13 imageViewId = ivi; 14 textViewId = tvi; 15 isCenterCrop = centerCrop; 16} 17 18 @ Override19 public ViewHolder onCreateViewHolder (final ViewGroup parent, int viewType) {20 View = LayoutInflater. from (context ). inflate (layoutResId, parent, false); 21 return new ViewHolder (view, imageViewId, textViewId); 22} 23 24 @ Override25 public void onBindViewHolder (ViewHolder holder, final int position) {26 final Animal animal = datas. get (position); 27 if (isCenterCrop) 28 Glide. with (context ). load (animal. getImgResId ()). centerCrop (). into (holder. imageView); 29 else30 Glide. with (context ). load (animal. getImgResId ()). into (holder. imageView); 31 holder. textView. setText (animal. getDescription (); 32 holder. view. setOnClickListener (new View. onClickListener () {33 @ Override34 public void onClick (View v) {35 Intent intent = new Intent (context, DetailActivity. class); 36 intent. putExtra ("IMG_RES_ID", animal. getImgResId (); 37 intent. putExtra ("DESCRIPTION", animal. getDescription (); 38 context. startActivity (intent); 39} 40}); 41 holder. view. setOnLongClickListener (new View. onLongClickListener () {42 @ Override43 public boolean onLongClick (View v) {44 Toast. makeText (context, "nth" + position + "element", Toast. LENGTH_SHORT ). show (); 45 return true; 46} 47}); 48} 49 50 @ Override51 public int getItemCount () {52 return datas. size (); 53} 54 55 public void addItem (int position) {56 datas. add (position, ResourceUtils. getRandomAnimal (); 57 policyiteminserted (position); 58} 59 60 public void removeItem (int position) {61 if (position> = 0 & position <datas. size () {62 datas. remove (position); 63 policyitemremoved (position); 64} 65} 66 67 static class ViewHolder extends RecyclerView. viewHolder {68 View view; 69 ImageView imageView; 70 TextView textView; 71 72 public ViewHolder (View itemView, int ivi, int tvi) {73 super (itemView); 74 view = itemView; 75 imageView = (ImageView) itemView. findViewById (ivi); 76 textView = (TextView) itemView. findViewById (tvi); 77} 78} 79}
Note:
- The Animal class encapsulates the resource ID and a description string of an (Animal) image. The Animal object will be used as an element in our RecyclerView;
- The onCreateViewHolder method is used to create a ViewHolder. Therefore, we need to provide the resource file ID used by an element, and the view we need to use (Here we include an ImageView and a TextView) can all be obtained through this ViewHolder;
- The onBindViewHolder method is used to set some views. Here we set the image for the ImageView, set the text for the TextView, and register the click and long-press listener for their parent view;
- Here, the addItem and removeItem methods are custom methods used to add/remove an element to/from RecyclerView (which will be described later), which can be ignored first;
- The ViewHolder here is ViewAdapter. ViewHolder, which inherits from RecyclerView. ViewHolder. We will hand over the view to it for management.
After the Adapter is defined, you can set the Adapter for RecyclerView:
1 List<Animal> datas= ResourceUtils.getAnimals();2 adapter=new ViewAdapter(this, datas, R.layout.item_vertical, R.id.vert_image, R.id.vert_text, true);3 view.setAdapter(adapter);
Vertical layout
To make RecyclerView use the same layout as ListView, you just need to set a linear layout manager for RecyclerView:
1 view.setLayoutManager(new LinearLayoutManager(this));
Horizontal Layout
To use horizontal layout, you only need to set the LinearLayoutManager direction:
1 LinearLayoutManager layoutManager=new LinearLayoutManager(this);2 layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);3 view.setLayoutManager(layoutManager);
Grid layout
The GridLayoutManager class is required for grid layout:
1 GridLayoutManager manager=new GridLayoutManager(this, 3);2 // manager.setOrientation(GridLayoutManager.HORIZONTAL);3 view.setLayoutManager(manager);
When GridLayoutManager is created, the second parameter uses the number of columns/number of rows. GridLayoutManager slides up and down by default. If you want to slide left and right, you can cancel the comments on the second line.
Waterfall flow Layout
To use waterfall stream layout, you only need to use StaggeredGridLayoutManager:
1 view.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
The first parameter of StaggeredGridLayoutManager specifies the number of columns/number of rows, and the second parameter specifies the sliding direction. Here it is set to slide up and down. If StaggeredGridLayoutManager is used with the same size of all elements, the effect is the same as that of grid layout.
Add split line
RecyclerView does not display the split line by default, which is different from ListView, but it also provides an opportunity to customize its own split line more flexibly.
To customize your own split line, You need to define the class inherited from RecyclerView. ItemDecoration and implement the following method:
- Void onDraw (Canvas c, RecyclerView parent, RecyclerView. State state): This method is used to draw the split line;
- Void onDrawOver (Canvas c, RecyclerView parent, RecyclerView. state state): This method is the same as the onDraw method, which is used to draw the split line. However, after the Element View is drawn, you only need to override onDraw and one of the methods;
- Void getItemOffsets (Rect outRect, View view, RecyclerView parent, RecyclerView. State state): This method calculates the split line size to calculate the offset of the element View.
Here, we will take the vertical layout of the split line as an example to introduce how to define your own split line. For other layout split lines, you can refer to it. The article will also provide all the source code:
1 public class VerticalItemDecoration extends RecyclerView.ItemDecoration { 2 private Drawable divider; 3 private static final int[] ATTRS=new int[] { 4 android.R.attr.listDivider, 5 }; 6 7 public VerticalItemDecoration(Context c) { 8 TypedArray array=c.obtainStyledAttributes(ATTRS); 9 divider=array.getDrawable(0);10 array.recycle();11 }12 13 @Override14 public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {15 super.onDraw(c, parent, state);16 DecorationUtils.onVerticalDraw(c, parent, divider);17 }18 19 @Override20 public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {21 super.getItemOffsets(outRect, view, parent, state);22 int position=parent.getChildLayoutPosition(view);23 int childCount=parent.getAdapter().getItemCount();24 if((position+1)<childCount)25 outRect.set(0, 0, 0, divider.getIntrinsicHeight());26 }27 }
1 public class DecorationUtils { 2 public static void onVerticalDraw(Canvas c, RecyclerView parent, Drawable divider) { 3 int left=parent.getPaddingLeft(); 4 int right=parent.getWidth()-parent.getPaddingRight(); 5 6 for(int i=0; i<parent.getChildCount()-1; i++) { 7 View child=parent.getChildAt(i); 8 RecyclerView.LayoutParams params=(RecyclerView.LayoutParams) child.getLayoutParams(); 9 int top=child.getBottom()+params.bottomMargin;10 int bottom=top+divider.getIntrinsicHeight();11 divider.setBounds(left, top, right, bottom);12 divider.draw(c);13 }14 }15 // ...16 }
Here, the separator style uses the "listDivider" provided by Android. You can redefine the listDivider attribute to modify the split line style:
1 <!-- Base application theme. -->2 <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">3 <!-- Customize your theme here. -->4 <item name="colorPrimary">@color/colorPrimary</item>5 <item name="colorPrimaryDark">@color/colorPrimaryDark</item>6 <item name="colorAccent">@color/colorAccent</item>7 <item name="android:listDivider">@drawable/divider</item>8 </style>
Add an animation
You may wonder why RecyclerView needs to be animated. Isn't it just a slide? Is it a sliding animation?
In this case, when you need to Add/Remove elements to/from RecyclerView, if an element suddenly inserts or disappears, what do users feel? (do you think this APP is illegal ). If an animation displays or disappears when an element is added or removed, the user experience will be better. So here we add an animation for the element.
RecyclerView provides a default animation, which only requires a simple line of code:
1 view.setItemAnimator(new DefaultItemAnimator());
Now we have added an animation for the appearance/disappearance of the element. Then the question comes again. How can we Add/Remove elements?
Do you still remember the ViewAdapter we provided when we introduced the adapter above? At that time, you temporarily ignored two methods -- addItem and removeItem. These two methods are used to Add/Remove elements.
Now let's take a look at the details:
1 public void addItem(int position) { 2 datas.add(position, ResourceUtils.getRandomAnimal()); 3 notifyItemInserted(position); 4 } 5 6 public void removeItem(int position) { 7 if(position>=0 && position<datas.size()) { 8 datas.remove(position); 9 notifyItemRemoved(position);10 }11 }
Note that the policyiteminserted and policyitemremoved methods are called to notify the RecyclerView element to change.
Now you have an interface for adding/removing elements. You need to add interaction actions in the Activity. We provide a Toolbar (a component used to replace ActionBar) and two items. You can click these two items to add or remove elements:
1 @Override 2 protected void onCreate(Bundle savedInstanceState) { 3 // ... 4 Toolbar toolbar=(Toolbar) findViewById(R.id.toolbar); 5 setSupportActionBar(toolbar); 6 // ... 7 } 8 9 @Override10 public boolean onCreateOptionsMenu(Menu menu) {11 getMenuInflater().inflate(R.menu.toolbar, menu);12 return true;13 }14 15 @Override16 public boolean onOptionsItemSelected(MenuItem item) {17 switch (item.getItemId()) {18 case R.id.add:19 adapter.addItem(0);20 view.smoothScrollToPosition(0);21 break;22 case R.id.remove:23 adapter.removeItem(0);24 break;25 default:break;26 }27 return true;28 }29 }
Now you can see the animation effect when adding/removing elements.
Source code
The source code of the entire project has been uploaded to GitHub:
Https://github.com/jzyhywxz/RecyclerView