Gesture Sample Code

,

This section looks at the GesturesView page in the downloadable sample code and demonstrates the various events of the GestureListener class. You see how to move, rotate, and resize a UIElement using gestures. You also see how to provide an animation that responds to a flick gesture to send a UIElement hurtling across a page.

The view contains a Border. Within the Border we attach the GestureListener and subscribe to its various events:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
    <TextBlock x:Name="messageBlock"
            Style="{StaticResource PhoneTextNormalStyle}"
            VerticalAlignment="Top" />
    <Button Content="reset" Click="Button_Click"
            VerticalAlignment="Bottom"
            HorizontalAlignment="Left" />
    <Border x:Name="border"
            Width="300" Height="200"
            BorderBrush="{StaticResource PhoneBorderBrush}"
            BorderThickness="4,32,4,4"
            Background="{StaticResource PhoneAccentBrush}"
            RenderTransformOrigin="0.5,0.5"
            Opacity=".8"
            CacheMode="BitmapCache">
        <Border.RenderTransform>
            <CompositeTransform x:Name="compositeTransform"/>
        </Border.RenderTransform>
        <toolkit:GestureService.GestureListener>
            <toolkit:GestureListener
                Tap="HandleTap"
                DoubleTap="HandleDoubleTap"
                Hold="HandleHold"
                DragStarted="HandleDragStarted"
                DragDelta="HandleDragDelta"
                DragCompleted="HandleDragCompleted"
                Flick="HandleFlick"
                PinchStarted="HandlePinchStarted"
                PinchDelta="HandlePinchDelta"
                PinchCompleted="HandlePinchCompleted">
            </toolkit:GestureListener>
        </toolkit:GestureService.GestureListener>
    </Border>
</Grid>

A CompositeTransform is used to change the position, size, and rotation of the Border.

The following sections walk through each gesture event and show how the Border control is manipulated in response.

Handling the Tap, DoubleTap, and Hold Events

When the user performs a tap gesture, the HandleTap method in the code-beside is called. This method resets the CompositeTransform translate values to 0, which returns the Border to its original location.

void HandleTap(object sender, GestureEventArgs e)
{
    compositeTransform.TranslateX = compositeTransform.TranslateY = 0;
}

When the user performs a double tap gesture, the HandleDoubleTap method is called, which resets the amount of scaling applied to the Border, returning it to its original size.

void HandleDoubleTap(object sender, GestureEventArgs e)
{
    compositeTransform.ScaleX = compositeTransform.ScaleY = 1;
}

When a hold gesture is performed, the HandleHold method is called. This, in turn, calls the ResetPosition method, resetting the size and location of the Border.

void HandleHold(object sender, GestureEventArgs e)
{
    ResetPosition();
}

void ResetPosition()
{
    compositeTransform.TranslateX = compositeTransform.TranslateY = 0;
    compositeTransform.ScaleX = compositeTransform.ScaleY = 1;
    compositeTransform.Rotation = 0;
}

Dragging the Border Control

When a drag gesture is performed, the HandleDragStarted method is called. This method changes the background of the Border, like so:

void HandleDragStarted(object sender, DragStartedGestureEventArgs e)
{
    border.Background = dragBrush;
}

An event handler for the DragDelta event moves the element by the drag amount, via the translation properties of the CompositeTransform:

void HandleDragDelta(object sender, DragDeltaGestureEventArgs e)
{
    compositeTransform.TranslateX += e.HorizontalChange;
    compositeTransform.TranslateY += e.VerticalChange;
}

When the drag gesture completes, the DragCompleted event handler resets the Border background:

void HandleDragCompleted(object sender, DragCompletedGestureEventArgs e)
{
    border.Background = normalBrush;
}

Rotating and Scaling in Response to a Pinch Gesture

When a pinch gesture is detected, the Pinch event handler records the amount of rotation applied to the element, along with the scale of the element:

double initialAngle;
double initialScale;

void HandlePinchStarted(object sender, PinchStartedGestureEventArgs e)
{
    border.Background = pinchBrush;

    initialAngle = compositeTransform.Rotation;
    initialScale = compositeTransform.ScaleX;
}

A change in the pinch gesture raises the PinchDelta event, at which point the level of rotation is applied to the CompositeTransform, and the element is scaled up or down using the PinchGestureEventArgs.DistanceRatio property:

void HandlePinchDelta(object sender, PinchGestureEventArgs e)
{
    compositeTransform.Rotation = initialAngle + e.TotalAngleDelta;
    compositeTransform.ScaleX
        = compositeTransform.ScaleY = initialScale * e.DistanceRatio;
}

The completion of a pinch gesture sees the border’s background restored, as shown:

void HandlePinchCompleted(object sender, PinchGestureEventArgs e)
{
    border.Background = normalBrush;
}

Flick Gesture Animation

This section presents a technique for animating a UIElement in response to a flick gesture. When a flick occurs, we install a StoryBoard with a timeline animation, which performs a translation on the UIElement.

The detection of a flick gesture causes the Flick event handler, HandleFlick, to be called. This method calculates a destination point for the border control based on the velocity of the flick. It then creates an animation for the border using the custom AddTranslationAnimation. See the following excerpt:

const double brakeSpeed = 10;

void HandleFlick(object sender, FlickGestureEventArgs e)
{
    Point currentPoint = new Point(
        (double)compositeTransform.GetValue(
                        CompositeTransform.TranslateXProperty),
        (double)compositeTransform.GetValue(
                        CompositeTransform.TranslateYProperty));

    double toX = currentPoint.X + e.HorizontalVelocity / brakeSpeed;
    double toY = currentPoint.Y + e.VerticalVelocity / brakeSpeed;
    Point destinationPoint = new Point(toX, toY);

    var storyboard = new Storyboard { FillBehavior = FillBehavior.HoldEnd };

    AddTranslationAnimation(
        storyboard, border, currentPoint, destinationPoint,
        new Duration(TimeSpan.FromMilliseconds(500)),
        new CubicEase {EasingMode = EasingMode.EaseOut});

    storyboard.Begin();
}

The static method AddTranslationAnimation creates two DoubleAnimation objects: one for the horizontal axis, the other for the vertical axis. Each animation is assigned to the border’s CompositeTransform, as shown:

static void AddTranslationAnimation(Storyboard storyboard,
    FrameworkElement targetElement,
    Point fromPoint,
    Point toPoint,
    Duration duration,
    IEasingFunction easingFunction)
{
    var xAnimation = new DoubleAnimation
                            {
                                From = fromPoint.X,
                                To = toPoint.X,
                                Duration = duration,
                                EasingFunction = easingFunction
                            };
    var yAnimation = new DoubleAnimation
                            {
                                From = fromPoint.Y,
                                To = toPoint.Y,
                                Duration = duration,
                                EasingFunction = easingFunction
                            };

    AddAnimation(
        storyboard,
        targetElement.RenderTransform,
        CompositeTransform.TranslateXProperty,
        xAnimation);

    AddAnimation(
        storyboard,
        targetElement.RenderTransform,
        CompositeTransform.TranslateYProperty,
        yAnimation);
}

The static method AddAnimation associates an animation Timeline with a DependencyObject, which in this case is the Border control:

static void AddAnimation(
    Storyboard storyboard,
    DependencyObject dependencyObject,
    DependencyProperty targetProperty,
    Timeline timeline)
{
    Storyboard.SetTarget(timeline, dependencyObject);
    Storyboard.SetTargetProperty(timeline, new PropertyPath(targetProperty));
    storyboard.Children.Add(timeline);
}

When launched, the GestureView page allows the user to flick the Border element across the page. A reset button exists to reset the position of the Border if it happens to leave the visible boundaries of the page (see Figure 12.11).

Image

FIGURE 12.11 The Border can be moved, rotated, resized, and flicked in response to gesture events.

Toolkit gestures offer a high-level way of interpreting touch input data and make it easy to provide a natural and immersive experience for your users, without the bother of tracking low-level touch events.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.209.98