TouchUI - ScrollControls (part 9)

by Chris 4. December 2009 13:26

Now we have come to the heart of this series, as this is where the most important part of the TouchUI framework is implemented. It's the base control class for the controls that allow scrolling, and the implementation was derived in some parts from the excellent SmoothListBox by Fredrik Bornander.

As you will see when you look at the implementation, there are a lot of settings that you can use to modify the exact behavior, and here are some examples:

  • snapBackFactor: how fast should the control snap back when passed the top and bottom borders
  • dragDistanceFactor: factor to increase the actual speed of dragging
  • maxVelocity: maximum scrolling velocity
  • deaccelerationFactor: how fast should the scrolling decelerate when we let go
  • borderDeaccelerationFactor: same as before, but on the top and bottom borders

The action starts when the finger (mouse) is pushed down...

public override void MouseDown(Point p)
{
    mouseDownPoint = p;
    previousPoint = mouseDownPoint;
}

...and position is simply saved. This becomes useful as the finger is dragged...

public override void MouseMove(Point p)
{
    int delta = p.Y - previousPoint.Y;
    draggedDistance = delta;
    scroll(delta);
    previousPoint = p;
}

...the distance dragged is recorded for each movement, and also the control is scrolled accordingly:

private void scroll(int offset)
{
    ScrollTop += offset;
}

When the finger is finally released...

public override void MouseUp(Point p)
{
    velocity = Math.Min(Math.Max(dragDistanceFactor * draggedDistance,
        -maxVelocity), maxVelocity);
    draggedDistance = 0;
    DoAutomaticMotion();
}

...the speed is recorded and the main scrolling logic is called...

public virtual void DoAutomaticMotion()
{
    velocity *= deaccelerationFactor;
   
if(ScrollTop > 0 || ScrollTop + ScrollHeight < Rectangle.Height)
        velocity *= borderDeaccelerationFactor;
   
float deltaDistance = elapsedTime * velocity;
   
if(Math.Abs(deltaDistance) >= 1.0f)
        scroll((
int)deltaDistance);
   
else
    {
       
if(ScrollTop != 0)
        {
           
if(ScrollTop > 0)
                scroll(-
Math.Max(1, (int)(snapBackFactor * (float)(ScrollTop))));
           
else
            {
               
if(ScrollHeight > Rectangle.Height)
                {
                   
int bottomPosition = ScrollTop + ScrollHeight + Rectangle.Top;
                   
if(bottomPosition < Rectangle.Height)
                        scroll(
Math.Max(1, (int)(snapBackFactor *
                            (float)(Rectangle.Height - bottomPosition))));
                }
               
else
                    scroll(Math.Max(1, -((int)(snapBackFactor *
                        (float)ScrollTop))));
            }
        }
    }
}

...and it handles the automatic motion of the control when the finger is released. It also takes care of the handling of the borders, and the automatic negative scroll that occurs then the borders are passed.

Another important thing that happens in the MouseUp method is...

PointSelected = (Math.Abs(p.Y - mouseDownPoint.Y) < 5);
if(Math.Abs(mouseDownPoint.X - p.X) > 50)
    HorizontalGesture = mouseDownPoint.X - p.X;
else
    HorizontalGesture = 0;

...that indicate if something was selected in the control (difference between pressed and released vertical position is less that five pixels), and whether sweep gesture was made (difference between pressed and released horizontal position greater than fifty pixels).

Currently rated 5.0 by 4 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Chris | Compact Framework | User Interface | Windows Mobile

Comments

Add comment


(Will show your Gravatar icon)  

  Country flag

biuquote
  • Comment
  • Preview
Loading



Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen