"Android" unlimited scrolling Horizontalscrollview

Source: Internet
Author: User

This is a very simple feature, as a novice, take notes. Also provide a reference for other people in need.

First, Horizontalscrollview all know the use. It can be implemented like "desktop program" to switch pages around the effect. In general, the number of pages is fixed, but it is also possible to encounter a number of pages, such as dynamic loading photos, or as I need to achieve this time.

  Implementation features: Implement the day view of the calendar. One page indicates a day, turn right to the next day, to the left to the last day. And can be arbitrarily turned to any day. each page has a to-do list of the day (this is also written, here only unlimited left and right page).

Because every day is a page, it is unrealistic to load all the days into the ScrollView. Given the memory footprint, it's good to not put too much stuff in ScrollView. so just put 3 pages. as shown in the following:

There are only 3 pages in Horizontalscrollview. On page No. 0, turn left, let go of the moment, 1 pages disappear,-2 page load, and then smoothscroll to 1 pages. to the right. So you can ensure that you don't use too much memory, and you can turn pages indefinitely.

The implementation of the time also encountered a small problem, by the way also write down.

At first, I naturally thought of rewriting horizontalscrollview. That is, the kamhorizontalscrollviewin the code.

    1. The main thing is to rewrite the Ontouchevent method to handle user finger swipe events.
    2. Because each child view occupies one screen, can not appear two view each half of phenomenon, need to have a child view pagination method. In my Code, the public boolean scrolltopage (int), which passes in the page number, guarantees that it will slide to the correct position, not half-way.
    3. It is also important to note that when turning the page, in order to ensure that ScrollView only 3 pages, you need to add a delete sub view. Add and remove at the end of the problem, but at the first increase, all the child view will move backwards, at the first delete, all the child view will move forward, so these two operations need to immediately change the ScrollView scroll value to ensure that the screen is smooth. This is reflected in method public Boolean addleft (View), and public boolean removeleft ();

Here are some of the problems I have in writing the code:

1, after rewriting Horizontalscrollview, I initialize in the constructor function, add three initial sub view, error.

Workaround: When the constructor is called, ScrollView is not instantiated, so you cannot add a child view at this time. It should be added after instantiation. Override protected void Onfinishinflate () method to get the timing of the instantiation completion, initialized under this method.

  2. When I swipe around, I call Scrolltopage (1), but always swipe to page 2nd or No. 0. is not set on page 1th.

Solution: I spent a lot of time on this problem (in fact, if I took a look at the API to get it done quickly). With log, the left value of the new view is still 0 after AddView is found. Or, for the moment after the AddView, all the sub-view in layout is still in its original state. It was a while before it was rearranged. So I need to get them to rearrange the timing to scroll to the right place. The custom layouts previously written javase had a way of rewriting the layout, so this too. Plainly is onlayout method (I think is onmeasure, try not very tangled). In the onlayout method, all child view should be rearranged. (This point can try it yourself, first AddView, and then immediately get the location and size of the view just now, will find that all is 0.) Then you can get it again by pressing the key event and you will find the correct value. Because the time from AddView to the button was enough for him to rearrange. )

So by Linearlayout.addonlayoutchangelistener (listener), you can monitor the timing of the rearrangement. However, this method requires APILevel 11 and above. I was just using my G12 test, APILevel10. Although very tangled, I can only rewrite the linearlayout, that is, the code of Kamlinearlayout, as well as the custom listener Kamlayoutchangelistener. Rewrite is just to monitor onlayout in Android2.3.

In addition, a little bit of detail, the mechanism of page flipping in addition to the distance of the finger slide, as well as the speed of finger sliding. Three ways to write your own speedchange. Test the feeling effect is very good.

Finally, the source attached, comments written in more detail, hoping to help beginners. Don't take too many detours like I do. (Note change the name of the package)

Kamhorizontalscrollview.java

  1 package Com.kam.horizontalscrollviewtest.view;  2 3 Import COM.KAM.HORIZONTALSCROLLVIEWTEST.R;  4 5 Import Android.content.Context;  6 Import Android.graphics.Color;  7 Import Android.util.AttributeSet;  8 Import Android.util.DisplayMetrics; 9 Import Android.util.Log; Ten import android.view.Gravity; Import android.view.MotionEvent; Import Android.view.View; Import Android.view.ViewGroup; Import Android.widget.HorizontalScrollView; Android.widget.LinearLayout import; Android.widget.TextView import; + Import Android.widget.FrameLayout.LayoutParams; 18/* If you do not need to support Android2.3, you can replace all kamlinearlayout in your code with viewgroup*/class Kamhorizontalscrollview extends      Horizontalscrollview {The private static String tag = "Kamhorizontalscrollview"; 22 private context context; 23/* Records the current page ID (the day view can be the same as this value today's date) * */pageno=0 int; 25 26/* Save ViewGroup in ScrollView, if you do not need to support Android2.3, you can replace kamlinearlayout with viewgroup*/private kamlineArlayout childgroup = null; 28 29/* This is to judge the use of the left and right (personal preferences, in fact, do not need such a trouble) * */private int poscache[] = new INT[4]; -Private int startpos;         Public Kamhorizontalscrollview (context context, AttributeSet attrs, int defstyle) {35 Super (context, attrs, Defstyle); //TODO auto-generated constructor stub this.context=context;          Kamhorizontalscrollview (context context, AttributeSet Attrs) {(context, attrs); 41 TODO auto-generated constructor stub this.context=context; Kamhorizontalscrollview} (Context context) {(context);//TODO Auto-gener ated constructor stub This.context=context;         48} 49 50/* Override Touch event to determine left/right swipe */@Override ontouchevent public boolean (Motionevent ev) {53 Switch (ev.getaction ()) {motionevent.action_down:55 startpos = (int) Ev.getx (); 56/* For determining the speed of touch sliding */initspeedchange ((int) ev.getx ()); break; Motionevent.action_move Case: {60/* Update Touch Speed Information */movingspeedchange ((int) ev.getx ()); A.             motionevent.action_up:65 Case Motionevent.action_cancel: {66/* First judge left or right by speed */67 int speed = Releasespeedchange ((int) ev.getx ());             (speed>0) {nextPage (); 71} 72             if (speed<0) {prevpage (); return true; 75} 76 77                 /* This is based on the touch start and end position to determine left or right * * if (Math.Abs ((Ev.getx ()-startpos)) > GetWidth ()/4) {79                 if (Ev.getx ()-startpos > 0) {80/* Left */Bayi prevpage (); 82 } else {83/* right * * + NEXtpage ();             (+} +} else {87 */unchanged */scrolltopage (1); 89 } to return true; The "super.ontouchevent" (EV); 94} 95 96/* Complete instantiation */@Override 98 protected void Onfinishinflate () {super.onfinishinflate () ; LOG.I (Tag, "Onfinishinflate called!"); 101 init (); 102}103 104/* initialization, adding three child view*/105 private void init () {106 this.childgroup= (Kaml Inearlayout) Findviewbyid (r.id.container); 107/* Add Layoutchange listener */108 Childgroup.addkamlayoutchangelisten ER (listener); 109/* Calls its own Layoutchange listener (Android2.3 not supported) */110/*childgroup.addonlayoutchangelistener (Listen ER); */111 addright (Createexampleview ( -1)); 113 Addright (Createexampleview (0)); Addri Ght (Createexampleview (1)); 115}116/* Add listener */117 kamlayoutchangelistener listener = new KAMLAYOUTCHangelistener () {118 119 @Override120 public void Onlayoutchange () {121//TODO Auto-g Enerated method stub122 log.i (tag, "onlayoutchanged called!"); 123 Scrolltopage (1); 124}125};126/*127//Note that if you do not need to support Android2.3, you can replace the above listener with the listen below er128 Onlayoutchangelistener listener = new Onlayoutchangelistener () {129 @Override131 Pub LIC void Onlayoutchange (View arg0, int arg1, int arg2, int arg3,132 int arg4, int arg5, int arg6, int arg7 , int Arg8) {133//TODO auto-generated method stub134 log.i (tag, "onlayoutchanged called!");          135 scrolltopage (1); 136}137};138 */139 140/* Left page */141 public void PrevPage () {142 pageno--;143 Addleft (Createexampleview (PageNo-1)); 144 removeright (); 145}146 147/* Right turn Page */148 public void NextPage () {149 pageno++;150 addright (cReateexampleview (pageno+1)); 151 removeleft (); 152}153 154 155 * * Get a child's x-coordinate */156 private int ge Tchildleft (int index) {157 if (index>=0 && childgroup! = null) {158 if (index< childgroup.     Getchildcount ()) 159 return Childgroup.getchildat (Index). GetLeft ();}161 return 0;162 }163 164/**165 * Add View166 to the right * @param view needs to add View167 * @return True Add Success |false add failed 168 * /169 public boolean addright (view view) {View==null | | childgroup==null) return false;171 CHILDGR Oup.addview (view); 172 return true;173}174 175/**176 * Delete Right View177 * @return true Success |false lost Fail 178 */179 Public boolean removeright () {(Childgroup==null | | childgroup.getchildcount () <=0) Retu     RN false;181 Childgroup.removeviewat (Childgroup.getchildcount ()-1) 182 return true;183}184 185 /**186 * Add vie to the leftw187 * @param view needs to add View188 * @return True Add success |false add failed 189 */190 public boolean addleft (view view)         {191 if (View==null | | childgroup==null) return false;192 childgroup.addview (view, 0); 193 194 /* Because the view is added to the left, all the view's X coordinates are incremented, so you need to let the scrollview move along to keep it smooth from the screen. */195 int tmpwidth = View.getlayoutparams (). width;196 if (tmpwidth==0) tmpwidth=getwinwidth (); 197 Lo G.I (Tag, "The new View's width =" +view.getlayoutparams (). width); 198 This.scrollto (This.getscrollx () +tmpwidth, 0);      199 return true;201}202 203/**204 * Delete Left View205 * @return True success |false failed 206 */207 public boolean Removeleft () {208 if (Childgroup==null | | childgroup.getchildcount () <=0) return false;20 9 210/* Because the view is deleted on the left, all view's x-coordinates are reduced, so you need to let the scrollview move along. */211 int Tmpwidth=childgroup.getchildat (0). getwidth (); 212 Childgroup.removeviewat (0); 213 THIS.SCR OlltO ((int) (THIS.GETSCROLLX ()-tmpwidth), 0); 214 215 return true;216}217 218/**219 * Jump to the specified         Page * 221 * @param index jump page number 222 * @return223 */224 public boolean scrolltopage (int index) {225 if (childgroup==null) return false;226 if (index<0 | | index >= childgroup.getchildcount ()) return false; 227 Smoothscrollto (Getchildleft (index), 0); 228 return true;229}230 231 private int Getwinwidt H () {232 displaymetrics DM = new Displaymetrics (); 233//Get screen info 234 dm = context.getresources (). Get Displaymetrics (); 235 return dm.widthpixels;236}237 238 private int getwinheight () {239 Displaymet         Rics dm = new Displaymetrics (); 240//Get screen info 241 dm = context.getresources (). Getdisplaymetrics (); 242 return dm.heightpixels;243}244/* generates a Test view. You don't need this when you're really using it. */245 private View createexampleview (int index) {246 Layoutparams params = new Layoutparams (Getwinwidth (), Getwinheight ()), 247/* Set different background color to make the effect more obvious */248 int colorarr[] = {24  9 Color.rgb (Color.rgb, (+), 251 Color.rgb (180),         252 Color.rgb (+/-),};253 TextView Txtview = new TextView (context); 254 Txtview.setbackgroundcolor (colorarr[(index%4+4)% 4]) 255 Txtview.settext (Index + ""); txtview.settexts         Ize (+); 257 txtview.setgravity (Gravity.center); 258 txtview.setlayoutparams (params); 259 260 Return txtview;261}262 263 264/* The following method is just a personal preference, used to determine the speed at which the user's finger slides left and right.         */265 private void Initspeedchange (int x) {266 if (poscache.length<=1) return;267 poscache[0]=1;268 for (int i=1;i<poscache.length;i++) {269}271}272 private void Movingspeedchange (i NT x) {273 poscache[0]%=poscache.length-1;274 POscache[0]++;275//log.i (tag, "Touch Speed:" + (x-poscache[poscache[0])); 276 poscache[poscache[0]]=x;277 }278 private int Releasespeedchange (int x) {279 return Releasespeedchange (x, +); 280}281 Private int Releasespeedchange (int x,int limit) {282 poscache[0]%=poscache.length-1;283 poscache[0]++;284/* Detected The speed to the left is very large */285 if (poscache[poscache[0]]-x>limit) return 1;286/* Detects a large right speed */287 if (x-poscache[posc Ache[0]]>limit) return-1;288 289 return 0;290}291}

Kamlinearlayout.java (This class can be ignored if you do not need to support APILevel 10 and below)

 1 package Com.kam.horizontalscrollviewtest.view; 2 3 Import Android.content.Context; 4 Import Android.util.AttributeSet; 5 Import Android.widget.LinearLayout; 6 7 public class Kamlinearlayout extends LinearLayout {8 Kamlayoutchangelistener listener = NULL; 9 publi     c void Addkamlayoutchangelistener (Kamlayoutchangelistener listener) {this.listener=listener;12}13 14     Public Kamlinearlayout (Context context) {super (context); +//TODO auto-generated constructor Stub17 }18 Public Kamlinearlayout (context context, AttributeSet Attrs) {(context, attrs);             Do auto-generated constructor stub21}22 @Override25 public void OnLayout (Boolean changed,26 int l, int t, int r, int b) {super.onlayout (changed, L, T, R, b); if (this.listener!=null) This.lis Tener.onlayoutchange (); 29}30 31}32/* Custom Listener */33 Interface kamlayoutchangelistener{34 abstract VoiD Onlayoutchange (); 35 36} 

Mainactivity.java

 1 package com.kam.horizontalscrollviewtest; 2 3 Import android.support.v7.app.ActionBarActivity; 4 Import Android.os.Bundle; 5 Import Android.view.Menu; 6 Import Android.view.MenuItem; 7 8 public class Mainactivity extends Actionbaractivity {9 @Override11 protected void OnCreate (Bundle Savedin     Stancestate) {super.oncreate (savedinstancestate); Setcontentview (R.layout.kamhsview); 14}15 16 @Override17 public boolean Oncreateoptionsmenu (Menu menu) {Inflate the menu, this adds items to the AC     tion Bar If it is present.19 getmenuinflater (). Inflate (R.menu.main, menu); return true;21}22 23 @Override24 public boolean onoptionsitemselected (MenuItem Item) {+//Handle Action Bar item clicks here. The Action Bar Will26//automatically handle clicks on the Home/up button, so long27//As you specify a     Parent activity in androidmanifest.xml.28 int id = item.getitemid (); 29    if (id = = r.id.action_settings) {return true;31}32 return super.onoptionsitemselected ( Item); 33}34}

Kamhsview.xml

<?xml version= "1.0" encoding= "Utf-8"? ><com.kam.horizontalscrollviewtest.view.kamhorizontalscrollview Xmlns:android= "Http://schemas.android.com/apk/res/android" android:layout_width= "Match_parent" android:layou t_height= "Match_parent" android:id= "@+id/kamscrollview" android:fadingedge= "None" android:scrollbars=        "None" > <!--if you don't need to support Android2.3, you can replace the kamlinearlayout with the normal linearlayout <linearlayout        Android:id= "@+id/container1" android:layout_width= "match_parent" android:layout_height= "Match_parent" android:orientation= "Horizontal" > </linearlayout > <com.kam.horizontalscrollviewtest. View. Kamlinearlayout android:id= "@+id/container" android:layout_width= "Match_parent" android:layout_height = "Match_parent" android:orientation= "Horizontal" > </com.kam.horizontalscrollviewtest.view.kamlinea Rlayout></com.kam.Horizontalscrollviewtest.view.kamhorizontalscrollview> 


Androidmanifest is the default one, no change.

<?xml version= "1.0" encoding= "Utf-8"? ><manifest xmlns:android= "http://schemas.android.com/apk/res/ Android "    package=" com.kam.horizontalscrollviewtest "    android:versioncode=" 1 "    android:versionname=" 1.0 ">    <uses-sdk        android:minsdkversion=" 8 "        android:targetsdkversion="/>    < Application        android:allowbackup= "true"        android:icon= "@drawable/ic_launcher"        android:label= "@string /app_name "        android:theme=" @style/appbasetheme ">        <activity            android:name=". Mainactivity "            android:label=" @string/app_name ">            <intent-filter>                <action android:name = "Android.intent.action.MAIN"/>                <category android:name= "Android.intent.category.LAUNCHER"/>            </intent-filter>        </activity>    </application></manifest>

"Android" unlimited scrolling horizontalscrollview

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.