5 Replies Latest reply on Nov 2, 2012 3:17 AM by raegtime

    Make an hgroup within a scroller "snap"

    A Sad Sam

      I'm developing an app for mobile devices using Flash Builder 4.5 and am having trouble figuring out how to accomplish one aspect of my  app.

       

      I have an HGroup inside of a Scroller.  The HGroup has images whose width is the same as the screen's width. Now what I want, is to make the users able to scroll through these images, but if they would stop scrolling in a point where they could see half of one image and half of another image in the viewport, it would snap to the nearest image. A behaviour wich you can see in action in many mobile apps.

       

      I know that this must be accomplished by listening for the swipe event in the scroller, and then setting that scroller viewport's horizontalScrollPosition to the nearest acceptable position. If a user of an HTC EVO (480 width) would stop scrolling in the position 260, the scroller would than move to position 480. Now, what I don't know is actually how am I going to make this snapping work.

       

      So, can anyone give me some advice as to how can I accomplish this feature?

        • 1. Re: Make an hgroup within a scroller "snap"
          A Sad Sam Level 1

          Well, looks like I figured it out myself. To all of you who might come across this problem, here's the code:

           

          scroller.addEventListener(TransformGestureEvent.GESTURE_SWIPE, snapViewPort);

           

          protected function snapViewPort(event:TransformGestureEvent):void {
               var pos:Number = scroller.viewport.horizontalScrollPosition;
                var remainder:Number = pos % this.width;

              
               if(remainder > 0) {
                    if(remainder <= this.width/2) {
                         scroller.viewport.horizontalScrollPosition = pos - remainder;
                    } else{
                         scroller.viewport.horizontalScrollPosition = pos - remainder + this.width;
                    }
               }
          }

          • 2. Re: Make an hgroup within a scroller "snap"
            raegtime

            http://mootricks.blogspot.com/2011/09/flex-snapscroller.html (German Blog)

             

            package 

            {

                      import flash.events.MouseEvent;

                      import flash.events.TimerEvent;

                      import flash.utils.Timer;

             

                      import mx.core.ScrollPolicy;

             

                      import spark.components.Group;

                      import spark.components.Scroller;

             

                      public class SnapScroller extends Scroller

                      {

                                private var xStart:Number;

                                private var mouseUpDownXDistance : Number;

                                private var t:Timer;

                                private var nextHorizontalPosition: Number;

                                private var nextHorizontalPositionDistance : Number;

                                private var _twidth:Number;

                                private var _theight:Number;

                                private var lastDate:Date;

             

                                [Inspectable(category="General", type="Number", defaultValue="200")]

                                public function set theight(val:Number):void

                                {

                                          this.height = val;

                                          this._theight = val;

                                }

             

                                public function get theight():Number

                                {

                                          return theight;

                                }

             

                                public function SnapScroller()

                                {

                                          super();

             

                                          this.minHeight = 500;

             

                                          this.setStyle('horizontalScrollPolicy',ScrollPolicy.OFF);

                                          this.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);

                                }

             

                                protected function onMouseDown(event:MouseEvent):void

                                {

                                          this.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);

                                          if (t)

                                                    t.stop();

             

                                          xStart = mouseX;

                                          this.addEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);

                                }

             

                                protected function onMouseMove(event:MouseEvent):void

                                {

                                                    mouseUpDownXDistance = mouseX-xStart;

                                                    this.viewport.horizontalScrollPosition -= mouseUpDownXDistance;

                                                    xStart = mouseX;

                                }

             

                                protected function onMouseUp(event:MouseEvent):void

                                {

                                          this.removeEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);

             

                                          if(mouseUpDownXDistance > 0)

                                                    nextHorizontalPosition = (int(this.viewport.horizontalScrollPosition/this.width))*this.width;

              else

                                                    nextHorizontalPosition = (int(this.viewport.horizontalScrollPosition/this.width)+1)*this.width;

             

                                          if (nextHorizontalPosition > ((this.getElementAt(0) as Group).contentWidth)-this.width)

                                                    nextHorizontalPosition = ((this.getElementAt(0) as Group).contentWidth)-this.width;

             

                                          t = new Timer(1,0);

                                          t.addEventListener(TimerEvent.TIMER,timerEnds);

                                          lastDate = new Date();

                                          t.start();

             

                                }

             

                                protected function timerEnds(event:TimerEvent):void

                                {

                                          var timeDifferenzSinceLastTimerEnds:Date;

             

                                          if(lastDate)

                                                    timeDifferenzSinceLastTimerEnds = new Date(new Date().time-lastDate.time);

             

                                          this.lastDate = new Date();

             

                                          var updateTime:Number;

                                          if(timeDifferenzSinceLastTimerEnds)

                                                    updateTime = timeDifferenzSinceLastTimerEnds.milliseconds*.05;

             

             

                                          var distanceToTarget:Number = Math.abs(this.viewport.horizontalScrollPosition - nextHorizontalPosition);

             

                                          if(this.viewport.horizontalScrollPosition > nextHorizontalPosition)

                                                    this.viewport.horizontalScrollPosition -= updateTime*Math.sqrt(distanceToTarget);

             

              else

                                                    this.viewport.horizontalScrollPosition += updateTime*Math.sqrt(distanceToTarget);

             

                                          if (distanceToTarget < 10.0)

                                          {

                                                    this.viewport.horizontalScrollPosition = nextHorizontalPosition;

             

                                                    t.stop();

                                                    t.removeEventListener(TimerEvent.TIMER,timerEnds);

                                          }

                                }

                      }

            }

            • 3. Re: Make an hgroup within a scroller "snap"
              A Sad Sam Level 1

              That approach sounds good too, but it's got too many lines of code xD. I appreciate your help, some of that code might be of use one day, but for now I prefer sticking to my own version as it's simpler.

              • 4. Re: Make an hgroup within a scroller "snap"
                deepak.srinivasa

                Thank you raegtime for posting code here. This helped me in building an iOS PageControl like component for Flex.

                -Deepak.