Android uses Horizontalscrollview imitation Viewpager to design simple albums _android

Source: Internet
Author: User
Tags static class

Recently learned a video public class, talked about the use of Horizontalscrollview imitation Viewpager design a simple album, in fact, mainly used the idea of viewpager caching. This article refers to: Android custom Horizontalscrollview to create Super gallery effects (This article is roughly the same as what the public class says)

Here's a quick Viewpager caching mechanism

1. When entering the Viewpager, load the current page and the next page;

2. When sliding Viewpager to the next page, load the next page, this time the first page is not destroyed, loading the next page of the current page.

is actually loaded by default 3 pages, the current page, the previous page and the next page.

This horizontalscrollview is the default load of two pages, this should be noted, otherwise the scheduling code will make people dizzy.

Words not much said, on the code:

The code structure is shown below:

A view, a adapter, a mainactivity, I believe no explanation, we are quite clear, the typical MVC pattern ~

Package Com.ssa.horizontalscrollview.myview; 
Import Java.util.HashMap; 
 
Import Java.util.Map; 
 
Import Com.ssa.horizontalscrollview.myUtils.DisplayUtil; 
Import Android.content.Context; 
Import Android.graphics.Color; 
Import Android.util.AttributeSet; 
Import Android.util.Log; 
Import android.view.MotionEvent; 
Import Android.view.View; 
Import Android.view.View.OnClickListener; 
Import Android.widget.HorizontalScrollView; 
 
Import Android.widget.LinearLayout; public class Galleryhorizontalscrollview extends Horizontalscrollview implements Onclicklistener {private Linearl The width of the linearlayout private int mchildwidth;//child element in the Ayout mcontainer;//myhorizontalscrollview is private int mchildheight; The height of the child element is private int malllastindex;//The current last one is the index private int mdisplaylastindex;//The last one currently displayed the index private I NT mallfirstindex;//the current first index private Galleryhorizontalscrollviewadapter madapter;//data adapter private int MSCREENW idth;//screen width private int mcountOnescreen; 
 
  Private Map<view, integer> mviewpos = new Hashmap<view, integer> (); 
 
  Private Oncurrentimagechangelistener Moncurrentimagechangelistener; 
 
  Private Onclickimagechangelistener Monclickimagechangelistener; public void Setmoncurrentimagechangelistener (Oncurrentimagechangelistener mlistener) {This.moncurrentimagech 
  Angelistener = Mlistener; } public void Setmonclickimagelistener (Onclickimagechangelistener mlistener) {This.monclickimagechangelistener 
  = Mlistener; /** * Image Scrolling Callback interface */public interface Oncurrentimagechangelistener {void oncurrentimgchanged (int pos 
  Ition, view view); /** * Click the image when the callback interface/public interface Onclickimagechangelistener {void Onclickimagechangelistener 
  T position, view view); 
    Public Galleryhorizontalscrollview (context, AttributeSet attrs) {Super (context, attrs); Get screen width mscreenwidth = getresources (). getdisplaymetricS (). Widthpixels; /** * Initialize data, set adapter/public void InitData (Galleryhorizontalscrollviewadapter madapter) {This.madap 
    ter = Madapter; 
    Mcontainer = (linearlayout) getchildat (0); 
    Final View view = Madapter.getview (0, NULL, mcontainer); 
    Mcontainer.addview (view); if (Mchildheight = = 0 && mchildwidth = 0) {/*int w = View.MeasureSpec.makeMeasureSpec (0, View. 
      measurespec.unspecified); int h = View.MeasureSpec.makeMeasureSpec (0, View.MeasureSpec.UNSPECIFIED);//** * The note above is written by a teacher method, but I checked a lot of data, with parameters 0 and View.MeasureSpec.UNSPECIFIED is a less graceful approach; * Good practice should be * when view is match_parent, you cannot measure the size of the view (Ningyugang great God Said, is indeed such a matter, this specific reason to combine source analysis, you can look at the blog of the Great God * when the View width is the specific value, such as 100px: * int W =view.measurespec.makemeasurespe 
       C (View.MeasureSpec.EXACTLY); 
       * int h =view.measurespec.makemeasurespec (M, View.MeasureSpec.EXACTLY); 
       * View.measure (W, h); * When view is wide and high for Wrap_content when: * int w =view.measurespec.makemeasurespec ((1<<30)-1, View.MeasureSpec.AT_MOST); 
       * int h =view.measurespec.makemeasurespec ((1<<30)-1, View.MeasureSpec.AT_MOST); 
       * View.measure (W, h); 
      * * My view height is fixed 150dip, width is wrap_content/int heightpx = displayutil.dip2px (GetContext (), 150); 
      int W =view.measurespec.makemeasurespec ((1<<30)-1, View.MeasureSpec.AT_MOST); 
      int h =view.measurespec.makemeasurespec (HEIGHTPX, View.MeasureSpec.EXACTLY); 
      View.measure (W, h); 
      Mchildheight = View.getmeasuredheight (); 
      Mchildwidth = View.getmeasuredwidth (); 
      Calculates how many item Mdisplaylastindex = Mscreenwidth/mchildwidth per load; 
      Mcountonescreen = Mdisplaylastindex + 1; 
 
    Initfirstscreenchildren (Mdisplaylastindex + 1); }/** * Load the elements of the first screen * * @param mdisplaycountonescreen * * private void Initfirstscreenchildren (in T mdisplaycountonescreen) {Mcontainer = (linearlayout) getchildat (0); 
    Mcontainer.removeallviews (); 
    Mviewpos.clear (); 
      for (int i = 0; i < Mdisplaycountonescreen i++) {View view = Madapter.getview (i, NULL, mcontainer); 
      Wait for the perfect click event View.setonclicklistener (this); 
      Mcontainer.addview (view); 
      Mviewpos.put (view, i); 
    Malllastindex = i; 
    }//Initialize and refresh the interface if (null!= moncurrentimagechangelistener) {notifycurrentimgchanged (); } private void Notifycurrentimgchanged () {//Clear all background colors first, set to blue for when clicked (int i = 0; i < mcontainer.ge Tchildcount (); 
    i++) {Mcontainer.getchildat (i). SetBackgroundColor (Color.White); 
  } moncurrentimagechangelistener.oncurrentimgchanged (Mallfirstindex, Mcontainer.getchildat (0)); @Override public boolean ontouchevent (motionevent ev) {/* LOG.E ("X", GetX () + ""); LOG.E ("Childx", * mcontainer.getchildat (0). GetX () + ""); 
     LOG.E ("Rawx", GetLeft () + ""); 
 */   Switch (ev.getaction ()) {case MotionEvent.ACTION_MOVE:int scrollx = Getscrollx (); 
      LOG.E ("Scrollx", Scrollx + ""); 
      if (scrollx >= mchildwidth) {//load the next page, remove the first loadnextimg (); 
      } if (scrollx = = 0) {//Load previous page, remove last loadpreimg (); 
    } break; 
  return super.ontouchevent (EV); 
    The private void loadnextimg () {//array boundary value is computed if (Malllastindex = = 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 (++malllastindex, NULL, Mcontainer) in the container; 
    View.setonclicklistener (this); 
    Mcontainer.addview (view); 
 
    Mviewpos.put (view, Malllastindex); 
    The current first picture small sign mallfirstindex++; 
  If a scrolling listener is set to trigger if (Moncurrentimagechangelistener!= null) {notifycurrentimgchanged ();  } private void Loadpreimg () {if (Mallfirstindex = = 0) {return; 
    int index = Malllastindex-mcountonescreen; 
      if (index >= 0) {//Remove the last int oldviewpos = Mcontainer.getchildcount ()-1; 
      Mviewpos.remove (Mcontainer.getchildat (Oldviewpos)); 
      Mcontainer.removeviewat (Oldviewpos); 
      Place the added view in the first position view view = Madapter.getview (index, NULL, Mcontainer); 
      Mviewpos.put (view, index); 
      Mcontainer.addview (view, 0); 
      View.setonclicklistener (this); 
 
      Pixel Scrollto (mchildwidth, 0) that moves the width of the view to the left by the horizontal scrolling position; 
      malllastindex--; 
 
      mallfirstindex--; 
      if (null!= moncurrentimagechangelistener) {notifycurrentimgchanged (); @Override public void OnClick (View v) {if (Null!=monclickimagechangelistener) {Monclicki}}} 
    Magechangelistener.onclickimagechangelistener (Mviewpos.get (v), V); 
 } 
  } 
}

The following is the source code for adapter:

Package Com.ssa.horizontalscrollview.myview; 
 
Import java.util.List; 
 
Import COM.SSA.HORIZONTALSCROLLVIEW.R; 
Import Android.content.Context; 
Import Android.view.LayoutInflater; 
Import Android.view.View; 
Import Android.view.ViewGroup; 
Import Android.widget.ImageView; 
 
Import Android.widget.TextView; 
  public class Galleryhorizontalscrollviewadapter {private Layoutinflater minflater; 
 
  Private list<integer> Mdatas; Public Galleryhorizontalscrollviewadapter (context context, list<integer> Mdatas) {minflater = Layoutinflater.f 
    Rom (context); 
  This.mdatas = Mdatas; 
  Public Object getitem (int position) {return mdatas.get (position); 
  public long getitemid (int position) {return position; 
  public int GetCount () {return mdatas.size (); 
    Public View GetView (int position, View Contentview, ViewGroup parent) {Viewholder myholder = null; if (null = = Contentview) {Contentview = MinflateR.inflate (R.layout.activity_gallery_item, parent, false); 
      Myholder = new Viewholder (Contentview); 
    Contentview.settag (Myholder); 
    }else {Myholder = (Viewholder) contentview.gettag (); 
    } myHolder.ivImg.setImageResource (Mdatas.get (position)); 
     
     
    MyHolder.tvText.setText ("Img_" +position); 
  return contentview; 
    private static class Viewholder {ImageView ivimg; 
 
    TextView Tvtext; 
      Public Viewholder (view view) {ivimg = (ImageView) View.findviewbyid (r.id.iv_content); 
    Tvtext = (TextView) View.findviewbyid (R.id.tv_index); 
 } 
  } 
 
}

The following is the source code for mainactivity:

Package Com.ssa.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.widget.ImageView; 
Import Com.ssa.horizontalscrollview.myview.GalleryHorizontalScrollView; 
Import Com.ssa.horizontalscrollview.myview.GalleryHorizontalScrollView.OnClickImageChangeListener; 
Import Com.ssa.horizontalscrollview.myview.GalleryHorizontalScrollView.OnCurrentImageChangeListener; 
 
Import Com.ssa.horizontalscrollview.myview.GalleryHorizontalScrollViewAdapter; 
  public class Mainactivity extends activity {private Galleryhorizontalscrollview Mhorizontalscrollview; 
  Private Galleryhorizontalscrollviewadapter Madapter; 
  Private ImageView mimg; Private list<integer> Mdatas = new Arraylist<integer> (Arrays.aslist (R.drawable.a, r.drawable.b, R.draw ABLE.C, R.DRAWABLE.D, r.drawable.e,r.drawable.F,R.DRAWABLE.G)); 
    @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); 
    Setcontentview (R.layout.activity_main); 
    Mimg = (ImageView) Findviewbyid (r.id.iv_content); 
    Mhorizontalscrollview = (Galleryhorizontalscrollview) Findviewbyid (R.id.mhsv_gallery_container); 
    Madapter = new Galleryhorizontalscrollviewadapter (this, mdatas); 
      Mhorizontalscrollview.setmoncurrentimagechangelistener (New Oncurrentimagechangelistener () {@Override 
        public void oncurrentimgchanged (int position, view view) {Mimg.setimageresource (Mdatas.get (position)); 
      View.setbackgroundcolor (Color.parsecolor ("#6d9eeb")); 
    } 
    }); Mhorizontalscrollview.setmonclickimagelistener (New Onclickimagechangelistener () {@Override public V 
      OID Onclickimagechangelistener (int position, view view) {Mimg.setimageresource (Mdatas.get (position)); 
    } 
    }); MhorizoNtalscrollview.initdata (Madapter); 
 } 
}

To some, debug run, the reader will find that the entire album will be very card,

Even some pictures have not shown as img_4, look at Logcat, I believe you will find the reason:

The message is very clear, the picture is too large,

At this point we should understand that the author deliberately selected a few very large pictures loaded, although not big enough to direct the application to collapse, but experience has become very poor, this is because the classroom teacher lectures used in the pictures are dozens of K of the small picture, loading of course there will be no problem, so want to make this album as a Practical album, Still have to deal with picture too big problem, otherwise, still can cause oom.

This tool class is used at this time:

Package com.ssa.horizontalscrollview.myUtils; 
Import android.content.res.Resources; 
Import Android.graphics.Bitmap; 
 
Import Android.graphics.BitmapFactory; public class Bitmaputil {public static Bitmap decodesampledbitmapfromresources (resources res, int resid, int re 
    qwidth, int reqheight) {final bitmapfactory.options Options = new Bitmapfactory.options (); 
    Options.injustdecodebounds = true; 
    Bitmapfactory.decoderesource (res, resid, options); 
    Options.insamplesize = calculateinsamplesize (options, Reqwidth, reqheight); 
    Options.injustdecodebounds = false; 
 
  Return Bitmapfactory.decoderesource (res, resid, options); public static int Calculateinsamplesize (bitmapfactory.options Options, int reqwidth, int reqheight) {f 
    inal int height = options.outheight; 
    Final int width = options.outwidth; 
    int insamplesize = 1; if (Height > reqheight | | | width > reqwidth) {final int halfheight = height/ 2; 
      Final int halfwidth = WIDTH/2; 
        while ((halfheight/insamplesize) >= reqheight && (halfwidth/insamplesize) >= reqwidth) { 
      Insamplesize *= 2; 
  } return insamplesize; 
 } 
}

Added this tool class, the above several classes of code to be slightly modified, specific how to change, you can download the following I uploaded the source code:
As for the effect as shown in the motion diagram (generated GIF has a bit of a card, you can run to see the effect):

SOURCE download: Horizontalscrollview Imitation Viewpager Design Album

This is the entire content of this article, I hope to learn more about Android software programming help.

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.