What is Recyclerview
Recyclerview is one of the components in the Android 5.0 materials design, with CardView, palette, and so on. Look at the name we can see a clue, yes, its main feature is reuse. We know that Viewholder can be reused in adapter in ListView. Recyclerview provides a less coupled way to use viewholder and can easily achieve the effects of ListView, GridView, and waterfall flows.
The basic idea of using Recyclerview
first we want to add compile ' com.android.support:recyclerview-v7:21.+ ' to the Gradle library. If it is eclipse to import Android-support-v7-recyclerview.jar directly.
/**
* Set Adapter * *
mrecyclerview.setadapter (mlistadapter);
/**
* Set the layout manager
/Mrecyclerview.setlayoutmanager (Linearlayoutmanager);
/**
* Set the item split line * * *
mrecyclerview.additemdecoration (itemdecoration);
/**
* Set the item
animation
/mrecyclerview.setitemanimator (New Defaultitemanimator ());
Using Recyclerview, basically take four steps above. The use of Recyclerview seems to be more complicated than ListView just setting up adapter. But it's more customizable, you can customize your own split line style or the item's animation.
Achieve gallery effect
Recyclerview here can be seen as an upgraded version of the ListView, the next buy it first introduces the use of Recyclerview, and then a certain analysis, and finally customize the Recyclerview to achieve the album effect we need.
1, the basic use of Recyclerview
First, the layout file for the main activity:
<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= "http:// Schemas.android.com/tools "
android:layout_width=" match_parent "
android:layout_height=" Match_parent " >
<android.support.v7.widget.recyclerview
android:id= "@+id/id_recyclerview_horizontal"
Android:layout_width= "Match_parent"
android:layout_height= "120DP"
android:layout_centervertical= True "
android:background=" #FF0000 "
android:scrollbars=" "None"/>
</RelativeLayout>
Item's layout file:
<?xml version= "1.0" encoding= "Utf-8"?> <relativelayout xmlns:android= "http://schemas.android.com/apk/res/"
Android "Android:layout_width=" 120DP "android:layout_height=" 120DP "android:background=" @drawable/item_bg02 "> <imageview android:id= "@+id/id_index_gallery_item_image" android:layout_width= "80DP" android:layou t_height= "80DP" android:layout_alignparenttop= "true" android:layout_centerhorizontal= "true" Android:layout_
Margin= "5DP" android:scaletype= "Centercrop"/> <textview android:id= "@+id/id_index_gallery_item_text" Android:layout_width= "Wrap_content" android:layout_height= "wrap_content" android:layout_below= "@id/id_inde X_gallery_item_image "android:layout_centerhorizontal=" true "android:layout_marginbottom=" 5DP "Android:layo ut_margintop= "5DP" android:textcolor= "#ff0000" android:text= "some info" android:textsize= "12DP"/> &L
T;/relativelayout>
Data Adapters:
Package com.example.zhy_horizontalscrollview03;
Import java.util.List;
Import Android.content.Context;
Import Android.support.v7.widget.RecyclerView;
Import Android.view.LayoutInflater;
Import Android.view.View;
Import Android.view.ViewGroup;
Import Android.widget.ImageView;
Import Android.widget.TextView; public class Galleryadapter extends recyclerview.adapter<galleryadapter.viewholder> {private LAYOUTINFLA
ter Minflater;
Private list<integer> Mdatas;
Public Galleryadapter (context context, list<integer> datats) {minflater = Layoutinflater.from (context);
Mdatas = Datats;
public static class Viewholder extends Recyclerview.viewholder {public viewholder (View arg0) {
Super (ARG0);
} ImageView mimg;
TextView Mtxt;
@Override public int GetItemCount () {return mdatas.size (); /** * Create Viewholder */@Override public Viewholder OncreateviEwholder (viewgroup viewgroup, int i) {View view = Minflater.inflate (R.layout.activity_index_gallery_item,
ViewGroup, false);
Viewholder Viewholder = new Viewholder (view);
Viewholder.mimg = (imageview) view. Findviewbyid (R.id.id_index_gallery_item_image);
return viewholder;
/** * Set Value * * @Override public void Onbindviewholder (final viewholder viewholder, final int i) {
ViewHolder.mImg.setImageResource (Mdatas.get (i));
}
}
You can see a considerable change in the data adapter compared to the Baseadapter, which has 3 main methods:
- GetItemCount This needless to say, get the total number of entries
- Oncreateviewholder Create Viewholder
- Onbindviewholder bind data to Viewholder
Visible, Recyclerview to Viewholder also carried on a certain package, but if you look carefully, you will send a question, ListView inside a GetView return view for the item layout, then the appearance of the item where control?
In fact, the viewholder we create must inherit Recyclerview.viewholder, and this recyclerview.viewholder construct must pass into a view that is equivalent to our ListView GetView in the Convertview (that is, we need to inflate the item layout needs to be passed in).
Also, in ListView, Convertview is reused, in Recyclerview, the Viewholder is used as the unit of the cache, and Convertview is kept in Viewholder as the member variable of the Viewholder. , that is, assuming that there are no screens displaying 10 entries, you will create 10 Viewholder cache, each reused is viewholder, so he getview this method into Oncreateviewholder. Interested in printing their own log, under test.
Finally used in the activity:
Package com.example.zhy_horizontalscrollview03;
Import java.util.ArrayList;
Import Java.util.Arrays;
Import java.util.List;
Import android.app.Activity;
Import Android.os.Bundle;
Import Android.support.v7.widget.LinearLayoutManager;
Import Android.support.v7.widget.RecyclerView;
Import Android.view.Window;
public class Mainactivity extends activity {private Recyclerview Mrecyclerview;
Private Galleryadapter Madapter;
Private list<integer> Mdatas;
@Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Requestwindowfeature (Window.feature_no_title);
Setcontentview (R.layout.activity_main);
Initdatas ();
Get Control Mrecyclerview = (Recyclerview) Findviewbyid (r.id.id_recyclerview_horizontal);
Set the layout manager Linearlayoutmanager Linearlayoutmanager = new Linearlayoutmanager (this);
Linearlayoutmanager.setorientation (linearlayoutmanager.horizontal); MrecycLerview.setlayoutmanager (Linearlayoutmanager);
Set adapter Madapter = new Galleryadapter (this, mdatas);
Mrecyclerview.setadapter (Madapter); private void Initdatas () {Mdatas = new arraylist<integer> (Arrays.aslist (R.drawable.a, R.D
rawable.b, r.drawable.c, R.DRAWABLE.D, R.DRAWABLE.E, R.drawable.f, r.drawable.g, R.drawable.h, R.DRAWABLE.L));
}
}
It is also very convenient to use, the only difference is to set the LayoutManager, there is only one implementation class, is Linearlayoutmanager, can be set to horizontal or vertical.
Final Effect Chart:
The effect is very good, this is the basic usage of Recyclerview, but you will find a pit dad place, unexpectedly did not provide Setonitemclicklistener this callback, want so pit dad ...
2. Add Onitemclicklistener callback for Recyclerview
Although it does not provide, but add a onitemclicklistener for us is not a piece of cake ~
I decided to add this callback interface to the adapter:
Package com.example.zhy_horizontalscrollview03;
Import java.util.List;
Import Android.content.Context;
Import Android.support.v7.widget.RecyclerView;
Import Android.view.LayoutInflater;
Import Android.view.View;
Import Android.view.View.OnClickListener;
Import Android.view.ViewGroup;
Import Android.widget.ImageView;
Import Android.widget.TextView; public class Galleryadapter extends recyclerview.adapter<galleryadapter.viewholder> {/** * ItemClick The callback interface * @author Zhy */public interface Onitemclicklitener {void Onitemclick (view view, int posi
tion);
Private Onitemclicklitener Monitemclicklitener; public void Setonitemclicklitener (Onitemclicklitener monitemclicklitener) {This.monitemclicklitener = MOnItemClic
Klitener;
Private Layoutinflater Minflater;
Private list<integer> Mdatas; Public Galleryadapter (context context, list<integer> datats) {minflater = LAYOUTINFLAter.from (context);
Mdatas = Datats;
public static class Viewholder extends Recyclerview.viewholder {public viewholder (View arg0) {
Super (ARG0);
} ImageView mimg;
TextView Mtxt;
@Override public int GetItemCount () {return mdatas.size (); @Override public Viewholder Oncreateviewholder (viewgroup viewgroup, int i) {View view = Minflater.infla
Te (R.layout.activity_index_gallery_item, ViewGroup, false);
Viewholder Viewholder = new Viewholder (view);
Viewholder.mimg = (imageview) view. Findviewbyid (R.id.id_index_gallery_item_image);
return viewholder; @Override public void Onbindviewholder (final viewholder viewholder, final int i) {viewHolder.mImg.setIm
Ageresource (Mdatas.get (i)); If a callback is set, set the Click event if (Monitemclicklitener!= null) {ViewHolder.itemView.setOnClickListener (new Onclickli Stener () {@Override
public void OnClick (View v) {Monitemclicklitener.onitemclick (Viewholder.itemview, i);
}
});
}
}
}
Simply, create an interface, provide a setup entry, and then judge it in Onbindviewholder.
Finally, set up the listener in the main activity:
Madapter = new Galleryadapter (this, mdatas);
Madapter.setonitemclicklitener (New Onitemclicklitener ()
{
@Override public
void Onitemclick View, int position)
{
toast.maketext (mainactivity.this, position+ "", Toast.length_short)
. Show ();
}
);
Mrecyclerview.setadapter (Madapter);
Okay, that's it, look at the effect chart:
The effect is still good, next I want to change to the album effect, that is, the above show a big picture, the following recyclerview as a picture of the switch indicator.
3, custom Recyclerview to achieve scrolling content linkage
first modify the following layout:
Layout file:
<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http:// Schemas.android.com/tools "android:layout_width=" match_parent "android:layout_height=" Match_parent "Android:orien"
tation= "vertical" > <framelayout android:layout_width= "fill_parent" android:layout_height= "0DP" android:layout_weight= "1" > <imageview android:id= "@+id/id_content" android:layout_width= "Fill_" Parent "android:layout_height=" fill_parent "android:layout_gravity=" center "android:layout_margin=" 10 DP "android:scaletype=" Centercrop "android:src=" @drawable/ic_launcher/> </FrameLayout> &l T;com.example.zhy_horizontalscrollview03. Myrecyclerview android:id= "@+id/id_recyclerview_horizontal" android:layout_width= "Match_parent" Android:lay out_height= "120DP" android:layout_gravity= "Bottom" android:background= "#FF0000" android:scrollbars= "None"/ >
</LinearLayout>
The
Adds a region that displays a larger image, changing the recyclerview to its own definition.
then look at our custom Recyclerview code:
Package com.example.zhy_horizontalscrollview03;
Import Android.content.Context;
Import Android.support.v7.widget.RecyclerView;
Import Android.util.AttributeSet;
Import android.view.MotionEvent;
Import Android.view.View; public class Copyofmyrecyclerview extends Recyclerview {public Copyofmyrecyclerview (context, attributeset a
Ttrs) {Super (context, attrs);
Private View Mcurrentview;
/** * The interface of the callback when scrolling * * Private onitemscrollchangelistener Mitemscrollchangelistener; public void Setonitemscrollchangelistener (Onitemscrollchangelistener mitemscrollchangelistener) {this.mIt
Emscrollchangelistener = Mitemscrollchangelistener;
public interface Onitemscrollchangelistener {void OnChange (view view, int position); @Override protected void OnLayout (Boolean changed, int l, int t, int r, int b) {super.onlayout (changed,
L, T, R, b);
Mcurrentview = Getchildat (0); if (MitemScrollchangelistener!= null) {Mitemscrollchangelistener.onchange (Mcurrentview, Getchildposition (M
CurrentView)); @Override public boolean ontouchevent (Motionevent e) {if e.getaction () = = Motionevent.action_mo
VE) {Mcurrentview = Getchildat (0);
LOG.E ("TAG", Getchildposition (Getchildat (0)) + ""); if (Mitemscrollchangelistener!= null) {Mitemscrollchangelistener.onchange (Mcurrentview, get
Childposition (Mcurrentview));
} return Super.ontouchevent (e);
}
}
Defines a scrolling callback interface, and then, in Ontouchevent, listens for Action_move, and the user's fingers slide, constantly returning the current first view callback.
about how I know Getchildat (0) and Getchildposition () are available, at first I thought there was getfirstvisibleitem this method, and then found out that there was, but Getrecycledviewpool () Look at the name I think is viewholder that cache queue, I think so directly to get the first of the queue is not the view I want to, then did not succeed. I observed the view inside of it, and found that the first one to show was always the first child, and as for getchildposition the way it looked.
Now the effect:
The effect was exactly the same as I did in the previous example, but I also wanted to make some changes, and I think gallery or an indicator of a photo album, which may 1000来 a picture, will automatically switch when I not only like to slide my finger on the screen. I also hope that if I give the indicator an acceleration, even if the fingers leave, the following is still sliding, the above will be linked. And I also want to do some optimization, directly in the Action_move callback, triggering the frequency is too high, theoretically a picture will only trigger once ~ ~
4, optimize and create the real gallery effect
since the hope that the finger left can also linkage, then not only need to action_move need to monitor, but also to monitor an acceleration, speed to reach a certain value, and then continue to move ~ ~ again to reason, need so trouble, not can roll mody, then there should be Onscrolllistener ah, Underestimate one, sure enough, hahaha ~ Heaven help me also, the following look at the modified code:
Package com.example.zhy_horizontalscrollview03;
Import Android.content.Context;
Import Android.support.v7.widget.RecyclerView;
Import Android.support.v7.widget.RecyclerView.OnScrollListener;
Import Android.util.AttributeSet;
Import Android.view.View; public class Myrecyclerview extends Recyclerview implements Onscrolllistener {/** * Record the current first view/Priva
Te View Mcurrentview;
Private Onitemscrollchangelistener Mitemscrollchangelistener; public void Setonitemscrollchangelistener (Onitemscrollchangelistener mitemscrollchangelistener) {this.mIt
Emscrollchangelistener = Mitemscrollchangelistener;
public interface Onitemscrollchangelistener {void OnChange (view view, int position);
Public Myrecyclerview (context, AttributeSet attrs) {Super (context, attrs);
TODO auto-generated Constructor stub this.setonscrolllistener (this); } @Override protected void OnLayout (Boolean ChangEd, int L, int t, int r, int b) {super.onlayout (changed, L, T, R, b);
Mcurrentview = Getchildat (0); if (Mitemscrollchangelistener!= null) {Mitemscrollchangelistener.onchange (Mcurrentview, GETCHILDP
Osition (Mcurrentview)); @Override public void onscrollstatechanged (int arg0) {}/** * * * To determine whether the current first view has changed
, occurred before callback/@Override public void onscrolled (int arg0, int arg1) {View Newview = getchildat (0);
if (Mitemscrollchangelistener!= null) {if (Newview!= null && newview!= mcurrentview) {
Mcurrentview = Newview;
Mitemscrollchangelistener.onchange (Mcurrentview, Getchildposition (Mcurrentview));
}
}
}
}
I give up rewriting the Ontouchevent method, but let this class implement the Recyclerview.onscrolllistener interface, and then set up the listener to judge in onscrolled.
As for optimization: I use a member change to store the current first view, only the first view changes when the callback ~ ~ Too perfect ~
See mainactivity:
Package com.example.zhy_horizontalscrollview03;
Import java.util.ArrayList;
Import Java.util.Arrays;
Import java.util.List;
Import android.app.Activity;
Import Android.os.Bundle;
Import Android.support.v7.widget.LinearLayoutManager;
Import Android.support.v7.widget.RecyclerView;
Import Android.view.View;
Import Android.view.Window;
Import Android.widget.ImageView;
Import Android.widget.Toast; Import com.example.zhy_horizontalscrollview03.
Galleryadapter.onitemclicklitener; Import com.example.zhy_horizontalscrollview03.
Myrecyclerview.onitemscrollchangelistener;
public class Mainactivity extends activity {private Myrecyclerview Mrecyclerview;
Private Galleryadapter Madapter;
Private list<integer> Mdatas;
Private ImageView mimg;
@Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Requestwindowfeature (Window.feature_no_title); Setcontentview (R.layout.activity_main);
Mimg = (ImageView) Findviewbyid (r.id.id_content); Mdatas = new Arraylist<integer> (Arrays.aslist (R.drawable.a, r.drawable.b, r.drawable.c, R.DRAWABLE.D, R.dra
WABLE.E, R.drawable.f, r.drawable.g, R.drawable.h, R.DRAWABLE.L));
Mrecyclerview = (Myrecyclerview) Findviewbyid (r.id.id_recyclerview_horizontal);
Linearlayoutmanager Linearlayoutmanager = new Linearlayoutmanager (this);
Linearlayoutmanager.setorientation (linearlayoutmanager.horizontal);
Mrecyclerview.setlayoutmanager (Linearlayoutmanager);
Madapter = new Galleryadapter (this, mdatas);
Mrecyclerview.setadapter (Madapter); Mrecyclerview.setonitemscrollchangelistener (New Onitemscrollchangelistener () {@Override public void on
Change (view view, int position) {Mimg.setimageresource (Mdatas.get (position));
};
}); Madapter.setonitemclicklitener (New Onitemclicklitener () {@Override PublIC void Onitemclick (view view, int position) {//Toast.maketext (Getapplicationcontext (), Position + "", Toa St.
Length_short)//. Show ();
Mimg.setimageresource (Mdatas.get (position));
}
});
}
}
No change in code ~ More Settings Callback ~
Effect Chart:
Can see not only support mobile phone in the above mobile changes, if I gave an acceleration, the following continuous scrolling, the above will continue to change ~ ~ Big Praise ~ Each picture callback once, the efficiency is quite good.
Well, read this blog, I believe that we have a certain understanding of recyclerview, even for how to transform a control also a more understanding ~ ~