Android Custom Recyclerview for true gallery effects

Source: Internet
Author: User

Reprint please indicate source: http://blog.csdn.net/lmj623565791/article/details/38173061, this articlefrom: "Zhang Hongyang's Blog"

Previous blog I used custom Horizontalscrollview to write a landscape picture carousel with Horizontalscrollview effects and Viewpager features, see: Android customization Horizontalscrollview creates more pictures (controls) and is not afraid of the lateral sliding effect of OOM. In fact, the production of horizontal scrolling has to say another control, is Google's latest addition to the new Recyclerview, is said to be the upgrade version of the ListView, this blog, first introduced the use of Recyclerview, and then a certain analysis Finally, customize the Recyclerview to achieve the album effect we need.

1. Basic usage of Recyclerview

First the main activity layout file:

<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>

The layout file for item:

<?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:l ayout_height= "80DP" android:layout_alignparenttop= "true" android:layout_centerhorizontal= "true" Andro Id:layout_margin= "5DP" android:scaletype= "Centercrop"/> <textview android:id= "@+id/id_index_galler Y_item_text "android:layout_width=" wrap_content "android:layout_height=" Wrap_content "Android:layout_ below= "@id/id_index_gallery_item_image" android:layout_centerhorizontal= "true" android:layout_marginbottom= " 5DP "android:layout_margintop=" 5DP "android:textcolor=" #ff0000 "android:text=" some info "Andro Id:textsize= "12DP"/></relaTivelayout> 

Data 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.viewgroup;import Android.widget.imageview;import Android.widget.textview;public class GalleryAdapter Extendsrecyclerview.adapter<galleryadapter.viewholder>{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;} @Overridepublic int GetItemCount () {return mdatas.size ();} /** * Create Viewholder */@Overridepublic viewholder Oncreateviewholder (viewgroup viewgroup, int i) {View view = MINFLATER.INFL Ate (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 */@Overridepublic void Onbindviewholder (Final viewholder viewholder, final int i) { ViewHolder.mImg.setImageResource (Mdatas.get (i));}}

You can see that the data adapter has changed considerably compared to the baseadapter, there are 3 main methods:

GetItemCount This needless to say, get the total number of entries

Oncreateviewholder Creating Viewholder

Onbindviewholder bind data to Viewholder

Visible, Recyclerview to Viewholder also carried out a certain encapsulation, but if you look closely, you will issue a question, the ListView has a GetView return to view the layout of the item, then the look of this item in what control?

In fact, the viewholder we create must inherit Recyclerview.viewholder, and this recyclerview.viewholder construct must pass in a view that is equivalent to our ListView Convertview in GetView (that is, we need the inflate item layout to be passed in).

Also, in the ListView, the Convertview is reused, in Recyclerview, the Viewholder is used as the unit of the cache, and then Convertview as the Viewholder member variable remains in Viewholder , that is, assuming that there are no screens showing 10 entries, 10 Viewholder are created and cached, and each is reused with viewholder, so he turns the GetView method into a oncreateviewholder. be interested in printing your own next 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; @Overrideprotected 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 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.drawable.b, R.drawable.c , R.DRAWABLE.D, R.drawable.e,r.drawable.f, r.drawable.g, R.drawable.h, R.DRAWABLE.L));}}

Use is also very convenient, the only difference is to set LayoutManager, currently only one implementation class, is Linearlayoutmanager, can be set to horizontal or vertical.

At last:


The effect is very good, this is the basic usage of Recyclerview, but you will find a pit daddy place, unexpectedly did not provide Setonitemclicklistener this callback, want not so pit dad ...

2. Add Onitemclicklistener callback for Recyclerview

Although it is not provided, but adding a onitemclicklistener for us is not a piece of cake ~

I decided to add this callback interface in 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 extendsrecyclerview.adapter<galleryadapter.viewholder>{ /** * ItemClick Callback interface * @author Zhy * */public interface onitemclicklitener{void onitemclick (view view, int position);} Private Onitemclicklitener monitemclicklitener;public void Setonitemclicklitener (Onitemclicklitener Monitemclicklitener) {this.monitemclicklitener = Monitemclicklitener;} 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;} @Overridepublic int GetItemCount () {return mdatas.size ();} @Overridepublic 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;} @Overridepublic void Onbindviewholder (Final viewholder viewholder, final int i) {ViewHolder.mImg.setImageResource ( Mdatas.get (i));//If a callback is set, set the Click event if (Monitemclicklitener! = null) {ViewHolder.itemView.setOnClickListener (new Onclicklistener () {@Overridepublic void OnClick (View v) {Monitemclicklitener.onitemclick (Viewholder.itemview, i);}});}}}

Very simply, create an interface, provide a setup entry, and then judge in Onbindviewholder.

Finally, the listener is set in the main activity:

Madapter = new Galleryadapter (this, mdatas); Madapter.setonitemclicklitener (new Onitemclicklitener () {@Overridepublic void Onitemclick (view view, int position) {Toast.maketext (Mainactivity.this, position+ "", Toast.length_short). Show ();}); Mrecyclerview.setadapter (Madapter);

All right, that's it, look:


The effect is still good, next I want to change into the album effect, that is shown above a large picture, the following recyclerview as a picture switch indicator.

3, custom Recyclerview implementation 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" a     Ndroid:layout_margin= "10DP" android:scaletype= "Centercrop" android:src= "@drawable/ic_launcher"/> </FrameLayout> <com.example.zhy_horizontalscrollview03. Myrecyclerview android:id= "@+id/id_recyclerview_horizontal" android:layout_width= "Match_parent" Andro id:layout_height= "120DP" android:layout_gravity= "Bottom" android:background= "#FF0000"android:scrollbars=" None "/></linearlayout> 

Add a region that displays a large map and change 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 context , AttributeSet Attrs) {Super (context, attrs);} Private View mcurrentview;/** * Callback interface */private Onitemscrollchangelistener mitemscrollchangelistener;public void when scrolling Setonitemscrollchangelistener (Onitemscrollchangelistener mitemscrollchangelistener) { This.mitemscrollchangelistener = Mitemscrollchangelistener;} public interface Onitemscrollchangelistener{void OnChange (view view, int position);} @Overrideprotected void OnLayout (Boolean changed, int l, int t, int r, int b) {super.onlayout (changed, L, T, R, b); mcurrent View = Getchildat (0), if (mitemscrollchangelistener! = null) {Mitemscrollchangelistener.onchange (Mcurrentview, Getchildposition (Mcurrentview));}} @Overridepublic Boolean OntouchevenT (motionevent e) {if (e.getaction () = = Motionevent.action_move) {Mcurrentview = Getchildat (0);//LOG.E ("TAG", Getchildposition (Getchildat (0)) + ""); if (mitemscrollchangelistener! = null) {Mitemscrollchangelistener.onchange ( Mcurrentview,getchildposition (Mcurrentview));}} Return Super.ontouchevent (e);}}

Define a scrolling callback interface, and then in the Ontouchevent, listen to the Action_move, the user's finger swipe, constantly put the current first view callback back ~

about how I know Getchildat (0) and Getchildposition () available, at first I thought there was getfirstvisibleitem this method, and later found that there is, but found Getrecycledviewpool () Look at the name I think is viewholder that cache queue, I think that the first to take this queue directly is not the view I want, and then did not succeed. I looked at it inside the view, finally found that the first display is always its first child, as for the getchildposition this look at the method.

Now the effect:



And my previous example of the effect is exactly the same, but I also want to make some changes, I think gallery or album indicator, below may 1000来 picture, I not only like the finger on the screen when the picture will automatically switch. I also hope that if I give the indicator an acceleration, even if the finger leaves, the bottom is still sliding, the above will also linkage. And I also want to do some optimization, directly in the Action_move callback, the frequency of triggering is too high, in theory, a picture will only trigger once ~ ~

4, optimize and build the gallery effect

Since the hope that the finger left can also linkage, then not only need action_move need to listen, but also to listen to an acceleration, speed to a certain value, and then continue to move ~ ~ Again, need so trouble, not can roll, then there should be onscrolllistener ah, underestimate a, Sure enough, hahaha ~ Heaven help me also, below see the revised 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{/** * Records the current first view */private view Mcurrentview;private Onitemscrollchangelistener mitemscrollchangelistener;public void Setonitemscrollchangelistener (Onitemscrollchangelistener Mitemscrollchangelistener) {this.mitemscrollchangelistener = Mitemscrollchangelistener;} public interface Onitemscrollchangelistener{void OnChange (view view, int position);} Public Myrecyclerview (context context, AttributeSet Attrs) {Super (context, attrs);//TODO Auto-generated constructor Stubthis.setonscrolllistener (this);} @Overrideprotected void OnLayout (Boolean changed, int l, int t, int r, int b) {super.onlayout (changed, L, T, R, b); mcurrent View = Getchildat (0); if (Mitemscrollchangelistener! = nulL) {Mitemscrollchangelistener.onchange (Mcurrentview,getchildposition (Mcurrentview));}} @Overridepublic void onscrollstatechanged (int arg0) {}/** * * * Scrolls, determines whether the current first view is changed, occurs only after a callback */@Overridepublic void onscrolled (int arg0, int arg1) {View Newview = getchildat (0); if (mitemscrollchangelistener! = null) {if (Newview! = null &am p;& Newview! = Mcurrentview) {Mcurrentview = Newview; Mitemscrollchangelistener.onchange (MCurrentView, Getchildposition (Mcurrentview));}}}

Instead of rewriting the Ontouchevent method, I let this class implement the Recyclerview.onscrolllistener interface, and then set the listener to judge in onscrolled.

As for optimization: I used a member change to store the current first view, only callback when the first view changed ~ ~ 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; @Overrideprotected 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.drawable.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 () {@Overridepublic void OnChange (view view, int position) {Mimg.setimageresource ( Mdatas.get (position);};}); Madapter.setonitemclicklitener (New Onitemclicklitener () {@Overridepublic void Onitemclick (view view, int position) {// Toast.maketext (Getapplicationcontext (), Position + "", Toast.length_short)//.show (); Mimg.setimageresource ( Mdatas.get (position));}});}}

There's no change in the code ~ More Settings Callback ~


Can see not only support mobile phone on the change, if I gave an acceleration, the following continuous scrolling, the above will continue to change ~ ~ Great ~ each picture callback once, the efficiency is quite good.


Well, after reading this blog, I believe you have a certain understanding of recyclerview, and even for how to transform a control also a more understanding ~ ~


If you feel good, leave a message or a little praise, show me the support


SOURCE Click to download



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.