Android Custom Horizontalscrollview to build Super Gallery effect _android

Source: Internet
Author: User
Tags arrays

Since gallery was scrapped by Google, Google recommends using Viewpager and Horizontalscrollview to achieve gallery effects. Indeed Horizontalscrollview can achieve gallery effect, but horizontalscrollview there is a big problem, if you are only used to show a small number of pictures, should be no problem, But if I want Horizontalscrollview to be like Viewpager, you can bind the dataset (dynamically change the picture) and do it, no matter how many pictures are not oom (Viewpager has been initialized, recycled, at most 3 view). This blog first introduces the simple usage of horizontalscrollview, and then expands on it, customizing the Horizontalscrollview to implement the effect we mentioned above, like a screen that can display multiple view Viewpager, No amount of pictures are afraid of oom. The simple use of
1, Horizontalscrollview
Horizontalscrollview is actually a subclass of Framelayout, so there can only be a direct child view inside. We use to do gallery effect, the first choice of course is linearlayout, then the direction is set to level.
1), 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 " 
 > 
  
 

It's very simple, just a horizontalscrollview with a horizontal direction inside the linearlayout.
Mainactivity:

Package Com.example.zhy_horizontalscrollview; 
Import android.app.Activity; 
Import Android.os.Bundle; 
Import Android.view.LayoutInflater; 
Import Android.view.View; 
Import Android.view.Window; 
Import Android.widget.ImageView; 
Import Android.widget.LinearLayout; 
 
Import Android.widget.TextView; 
 public class Mainactivity extends activity {private LinearLayout mgallery; 
 Private int[] Mimgids; 
 
 Private Layoutinflater Minflater; 
 @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); 
 Requestwindowfeature (Window.feature_no_title); 
 Setcontentview (R.layout.activity_main); 
 Minflater = Layoutinflater.from (this); 
 InitData (); 
 
 Initview (); private void InitData () {mimgids = new int[] {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}; private void Initview () {mgallery = (linearlayout) Findviewbyid (r.id.id_gaLlery); 
   for (int i = 0; i < mimgids.length i++) {View view = Minflater.inflate (R.layout.activity_index_gallery_item, 
  MGallery, false); 
  ImageView img = (imageview) view. Findviewbyid (R.id.id_index_gallery_item_image); 
  Img.setimageresource (Mimgids[i]); 
  TextView txt = (TextView) view. Findviewbyid (R.id.id_index_gallery_item_text); 
  Txt.settext ("some info"); 
 Mgallery.addview (view); 
 } 
 } 
 
}

Very simple, I prepared some pictures directly under the drawble, and then the circulation to join the horizontalscrollview of the LinearLayout, the item layout is saved, the following will be affixed to the source code.
Effect Chart:

The effect is still good ~ if you only need to show a few pictures, directly use on it.
The following ready to go to the point, Horizontalscrollview no matter how many view is not recycled, when a certain amount of time will occur oom, the following describes how to rewrite Horizontalscollview implementation of the article began to say the effect.
2, Custom Horizontalscrollview
thought:
1, first, according to the size of the screen and the size of the item, the calculation can be a screen can load the maximum number of item, and then load the quantity item.
2, when the user right sliding (from right to left), sliding to a certain distance, load the next one, delete the first
3, when the user left sliding (from left to right), sliding to a certain distance, load the previous one, delete the last one
Look at the final effect chart:

In order to add some fun, do a similar photo album effect, support drag automatically change, and click Change ~ ~ is not very good ~
1), first look at the 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: Background= "@android: Color/white" android:orientation= "vertical" > <framelayout android:layout_width= "fill_p 
  Arent "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:l 
 
 Ayout_margin= "10DP" android:scaletype= "Centercrop" android:src= "@drawable/ic_launcher"/> </FrameLayout> <com.example.zhy_horizontalscrollview. Myhorizontalscrollview android:id= "@+id/id_horizontalscrollview" android:layout_width= "Wrap_content" Android: layout_height= "150DP" android:layout_gravity= "Bottom" android:background= "@android: Color/white" android: scrollbars= "None" > &LT LinearLayout android:id= "@+id/id_gallery" android:layout_width= wrap_content "android:layout_height=" wrap_content "Android:layout_gravity=" center_vertical "android:orientation=" horizontal "> </LinearLayout> </com. Example.zhy_horizontalscrollview. 
 Myhorizontalscrollview> </LinearLayout>

Nothing changed, except to change the class name to our custom class ~
2), and in order to be in line with international standards, we also have a adapter, similar to Baseadapter

Package Com.example.zhy_horizontalscrollview; 
 
Import java.util.List; 
Import Android.content.Context; 
Import Android.view.LayoutInflater; 
Import Android.view.View; 
Import Android.view.ViewGroup; 
Import Android.widget.BaseAdapter; 
Import Android.widget.ImageView; 
 
Import Android.widget.TextView; 
 public class Horizontalscrollviewadapter {private context mcontext; 
 Private Layoutinflater Minflater; 
 
 Private list<integer> Mdatas; 
 Public Horizontalscrollviewadapter (context context, list<integer> Mdatas) {this.mcontext = context; 
 Minflater = Layoutinflater.from (context); 
 This.mdatas = Mdatas; 
 public int GetCount () {return mdatas.size (); 
 Public Object getitem (int position) {return mdatas.get (position); 
 public long getitemid (int position) {return position; 
 Public View GetView (int position, View Convertview, ViewGroup parent) {Viewholder viewholder = null; if (Convertview = = null) {ViewholDer = new Viewholder (); 
  Convertview = Minflater.inflate (R.layout.activity_index_gallery_item, parent, false); 
  Viewholder.mimg = (ImageView) convertview. Findviewbyid (R.id.id_index_gallery_item_image); 
 
  Viewholder.mtext = (TextView) convertview. Findviewbyid (R.id.id_index_gallery_item_text); 
 Convertview.settag (Viewholder); 
 else {Viewholder = (Viewholder) convertview.gettag (); 
 } viewHolder.mImg.setImageResource (Mdatas.get (position)); 
 
 ViewHolder.mText.setText ("some info"); 
 return convertview; 
 Private class Viewholder {ImageView mimg; 
 TextView Mtext; 
 } 
 
}

3), see following first:

Package Com.example.zhy_horizontalscrollview; 
Import java.util.ArrayList; 
Import Java.util.Arrays; 
 
Import java.util.List; 
Import android.app.Activity; 
Import Android.graphics.Color; 
Import Android.os.Bundle; 
Import Android.view.View; 
Import Android.view.Window; 
 
Import Android.widget.ImageView; Import Com.example.zhy_horizontalscrollview. 
Myhorizontalscrollview.currentimagechangelistener; Import Com.example.zhy_horizontalscrollview. 
 
Myhorizontalscrollview.onitemclicklistener; 
 public class Mainactivity extends activity {private Myhorizontalscrollview Mhorizontalscrollview; 
 Private Horizontalscrollviewadapter Madapter; 
 Private ImageView mimg; Private list<integer> Mdatas = new Arraylist<integer> (Arrays.aslist (R.drawable.a, r.drawable.b, R.drawabl 
 
 E.C, R.DRAWABLE.D, R.DRAWABLE.E, R.drawable.f, r.drawable.g, r.drawable.h, R.DRAWABLE.L); @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); 
 Mhorizontalscrollview = (Myhorizontalscrollview) Findviewbyid (R.id.id_horizontalscrollview); 
 Madapter = new Horizontalscrollviewadapter (this, mdatas); 
   Add scrolling callback Mhorizontalscrollview. Setcurrentimagechangelistener (New Currentimagechangelistener () {@Override public void oncurrentimgchanged (int position, View viewindicator) {Mimg.setimageresource Mdatas.get (positio 
   n)); 
   Viewindicator.setbackgroundcolor (Color. Parsecolor ("#AA024DA4")); 
 } 
  }); Add Click Callback Mhorizontalscrollview.setonitemclicklistener (New Onitemclicklistener () {@Override public void onclic 
  K (view view, int position) {Mimg.setimageresource (Mdatas.get (position)); 
  View.setbackgroundcolor (Color.parsecolor ("#AA024DA4")); 
 } 
 }); 
 Set Adapter Mhorizontalscrollview.initdatas (Madapter); 
 } 
 
}

Is it a bit like ListView, initializing the data adapter, and then setting up the data adapter, then setting up a variety of callbacks ~ ~
If it's just a bunch of picture shows, similar to the product switch, more simple, there is no need to set up rolling monitoring and click to monitor the ~
4), last look at the custom Myhorizontalscrollview class

Package Com.example.zhy_horizontalscrollview; 
Import Java.util.HashMap; 
 
Import Java.util.Map; 
Import Android.content.Context; 
Import Android.graphics.Color; 
Import Android.util.AttributeSet; 
Import Android.util.DisplayMetrics; 
Import Android.util.Log; 
Import android.view.MotionEvent; 
Import Android.view.View; 
Import Android.view.View.OnClickListener; 
Import Android.view.WindowManager; 
Import Android.widget.HorizontalScrollView; 
 
Import Android.widget.LinearLayout; 
 Callback interface for public class Myhorizontalscrollview extends Horizontalscrollview implements Onclicklistener {/** * picture scrolling  * * * * @author Zhy */public interface Currentimagechangelistener {void oncurrentimgchanged (int position, View 
 Viewindicator); /** * Entry Click Callback * * @author Zhy */public interface Onitemclicklistener {void OnClick view, I 
 NT POS); 
 
 Private Currentimagechangelistener Mlistener; 
 
 Private Onitemclicklistener Monclicklistener; Private STatic final String TAG = "Myhorizontalscrollview"; 
 
 /** * Horizontallistview in the linearlayout * * Private linearlayout Mcontainer; 
 /** * child element Width * * private int mchildwidth; 
 /** * child element Height * * private int mchildheight; 
 /** * The current last picture of the index * * * private int mcurrentindex; 
 /** * The subscript of the current first picture/private int mfristindex; 
 /** * Current First view */private view mfirstview; 
 /** * Data Adapter * * Private horizontalscrollviewadapter madapter; 
 /** * The maximum number of display per screen * * private int mcountonescreen; 
 
 
 /** * Screen Width * * private int MSCREENWITDH; 
 
 /** * Save View and location of the key value to the * * Private Map<view, integer> mviewpos = new Hashmap<view, integer> (); 
 Public Myhorizontalscrollview (context, AttributeSet attrs) {Super (context, attrs); 
 Get screen width windowmanager wm = (WindowManager) context. Getsystemservice (Context.window_service); 
 Displaymetrics outmetrics = new Displaymetrics (); 
 Wm.getdefaultdisplay (). Getmetrics (Outmetrics); MScREENWITDH = Outmetrics.widthpixels; @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (widthmeasure 
 Spec, Heightmeasurespec); 
 Mcontainer = (linearlayout) getchildat (0);  
 /** * Load Next picture * * protected void loadnextimg () {//Array boundary value calculation if (Mcurrentindex = = Madapter.getcount ()-1) 
 {return; 
 //Remove the first picture and place the horizontal scrolling position 0 scrollto (0, 0); 
 Mviewpos.remove (Mcontainer.getchildat (0)); 
  
 Mcontainer.removeviewat (0); 
 Gets the next picture and sets the OnClick event, and adds the view view = Madapter.getview (++mcurrentindex, NULL, Mcontainer) in the container; 
 View.setonclicklistener (this); 
 Mcontainer.addview (view); 
  
 Mviewpos.put (view, Mcurrentindex); 
 The current first picture small sign mfristindex++; 
 If a scrolling listener is set to trigger if (Mlistener!= null) {notifycurrentimgchanged (); 
 }/** * Before loading a picture/protected void loadpreimg () {//If the current is already the first one, return if (Mfristindex = = 0) returns; 
 Gets the subscript int index = Mcurrentindex-mcountonescreen that should now be displayed as the first picture; if (inDex >= 0) {//Mcontainer = (linearlayout) getchildat (0); 
  Remove the last int oldviewpos = Mcontainer.getchildcount ()-1; 
  Mviewpos.remove (Mcontainer.getchildat (Oldviewpos)); 
  
  Mcontainer.removeviewat (Oldviewpos); 
  Put this view in the first position view view = Madapter.getview (index, NULL, Mcontainer); 
  Mviewpos.put (view, index); 
  Mcontainer.addview (view, 0); 
  View.setonclicklistener (this); 
  The horizontal scrolling position moves the width of the view to the left pixel Scrollto (mchildwidth, 0); 
  Current position------mcurrentindex--; 
  mfristindex--; 
 
  Callback if (Mlistener!= null) {notifycurrentimgchanged (); The callback/public void notifycurrentimgchanged () {////** * when sliding * ()}}} {//Clear all background colors first, set to blue for when clicked (int i = 0; i < Mcontainer.getchildcount (); 
 i++) {Mcontainer.getchildat (i). SetBackgroundColor (Color.White); 
 
 } mlistener.oncurrentimgchanged (Mfristindex, Mcontainer.getchildat (0)); /** * Initialize data, SET data adapter * * @param madapter/public void Initdatas (HorizontalscrollvieWadapter madapter) {this.madapter = Madapter; 
 Mcontainer = (linearlayout) getchildat (0); 
 Get the first view final view view = Madapter.getview (0, NULL, Mcontainer) in the adapter; 
 
 Mcontainer.addview (view); 
   Forces the width and height of the current View to be calculated (Mchildwidth = 0 && mchildheight = 0) {int w = View.MeasureSpec.makeMeasureSpec 0, 
  View.MeasureSpec.UNSPECIFIED); 
  int h = View.MeasureSpec.makeMeasureSpec (0, View.MeasureSpec.UNSPECIFIED); 
  View.measure (W, h); 
  Mchildheight = View.getmeasuredheight (); 
  Mchildwidth = View.getmeasuredwidth (); 
  LOG.E (TAG, view.getmeasuredwidth () + "," + view.getmeasuredheight ()); 
  Mchildheight = View.getmeasuredheight (); 
 
  Calculates how many view Mcountonescreen = mscreenwitdh/mchildwidth+2 per load; 
  
 
 LOG.E (TAG, "mcountonescreen =" + Mcountonescreen + ", Mchildwidth =" + mchildwidth); 
 }//Initialize the element Initfirstscreenchildren (Mcountonescreen) of the first screen; /** * Load First screen view * * @param mcountonescreen/public void InitfirstscreenchIldren (int mcountonescreen) {Mcontainer = (linearlayout) getchildat (0); 
 Mcontainer.removeallviews (); 
 
 Mviewpos.clear (); 
  for (int i = 0; i < Mcountonescreen i++) {View view = Madapter.getview (i, NULL, mcontainer); 
  View.setonclicklistener (this); 
  Mcontainer.addview (view); 
  Mviewpos.put (view, i); 
 Mcurrentindex = i; 
 } if (Mlistener!= null) {notifycurrentimgchanged (); @Override public boolean ontouchevent (motionevent ev) {switch (ev.getaction ()) {case MOTIONEVENT.A 
 
  Ction_move://LOG.E (TAG, GETSCROLLX () + ""); 
  int scrollx = GETSCROLLX (); 
  If the current scrollx is the width of the view, load the next one, remove the first if (Scrollx >= mchildwidth) {loadnextimg (); 
  //If the current SCROLLX = 0, set forward one, remove the last if (Scrollx = = 0) {loadpreimg (); 
 } break; 
 return super.ontouchevent (EV); @Override public void OnClick (View v) {if (Monclicklistener!= null) {for (int i = 0; i < Mcontainer . Getchildcount (); i++) {
  Mcontainer.getchildat (i). SetBackgroundColor (Color.White); 
 } monclicklistener.onclick (V, Mviewpos.get (v)); } public void Setonitemclicklistener (Onitemclicklistener monclicklistener) {This.monclicklistener = MOnClickL 
 Istener; } public void Setcurrentimagechangelistener (Currentimagechangelistener mlistener) {This.mlistener = MListener 
 ; 
 } 
 
}

First, load the first item, calculate how many pictures the current screen can load according to the item's width, and then initialize the first screen's picture, then write the ontouchevent, listen to the user's action_move, and then load the previous or the next one according to the moving distance, Dynamic removal of Invisible view, reclaim memory ~ ~ ~ ~
There is a map in the code that stores view and posion, mainly to provide the click callback with the current view location, a bit like this: Android custom Viewpager Create the ingenious use of map in the ever-changing picture switching effect ~ ~
is not fully realized Viewpager and horizontalscrollview of the ~~~horizontalscrollview effect, Viewpager characteristics ~ ~ ~ ~
Finally, after the rotation screen, the effect chart:

Can be seen, not only to do albums, or pictures of the carousel thought are just!

SOURCE Download: Horizontalscrollview to create super strong gallery effect

If you need to use a gallery similar effect in your project, use the example to try it decisively!

Related Article

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.