Skip to content

davidezordan/MultiTouch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

45 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Multi-Touch Behaviors

XAML Behaviors implementing Multi-Touch Manipulation (Gestures) and Inertia.

Xamarin Forms Behavior uses code from original Xamarin.Forms samples: https://github.com/xamarin/xamarin-forms-samples/tree/master/WorkingWithGestures

Archived projects targeting Silverlight, WPF and Windows Phone 7.x, 8.x available on CodePlex: http://multitouch.codeplex.com/.

Xamarin.Forms: using the PanGestureRecognizer

Using the PanGestureRecognizer

Recently I've blogged about Xamarin.Forms and how to create a XAML Behavior for enabling Multi-Touch gestures to generic elements and implementing a scale / pinch functionality.

Fortunately the framework provides three types of recognizer that greatly simplify the implementation:

  • PinchGestureRecognizer allows user interactions for zoom / scale functionalities;
  • PanGestureRecognizer enables pan / translate transformations;
  • TapGestureRecognizer detects tap events.

Yesterday I decided to try the PanGestureRecognizer for extending the capabilities of the Behavior described in the previous post.

First of all, I added two Bindable properties in order to permit activation / deactivation of individual gestures (Bindable properties are equivalent to Dependency ones in UWP XAML)

#region IsScaleEnabled property

/// <summary>
/// Identifies the <see cref="IsScaleEnabledProperty" /> property.
/// </summary>
public static readonly BindableProperty IsScaleEnabledProperty =
    BindableProperty.Create<MultiTouchBehavior, bool>(w => w.IsScaleEnabled, default(bool));

/// <summary>
/// Identifies the <see cref="IsScaleEnabled" /> dependency / bindable property.
/// </summary>
public bool IsScaleEnabled
{
    get { return (bool)GetValue(IsScaleEnabledProperty); }
    set { SetValue(IsScaleEnabledProperty, value); }
}

#endregion

#region IsTranslateEnabled property

/// <summary>
/// Identifies the <see cref="IsTranslateEnabledProperty" /> property.
/// </summary>
public static readonly BindableProperty IsTranslateEnabledProperty =
    BindableProperty.Create<MultiTouchBehavior, bool>(w => w.IsTranslateEnabled, default(bool));

/// <summary>
/// Identifies the <see cref="IsTranslateEnabled" /> dependency / bindable property.
/// </summary>
public bool IsTranslateEnabled
{
    get { return (bool)GetValue(IsTranslateEnabledProperty); }
    set { SetValue(IsTranslateEnabledProperty, value); }
}

#endregion

In this way we can specify in our XAML what gestures are enabled:

...
<Image.Behaviors>
     <behaviors:MultiTouchBehavior IsScaleEnabled="True" IsTranslateEnabled="True" />
</Image.Behaviors>
...

Then I initialised the GestureRecognizers adding a new PanGestureRecognizer to the recognizers list:

/// <summary>
/// Initialise the Gesture Recognizers.
/// </summary>
private void InitialiseRecognizers()
{
    _panGestureRecognizer = new PanGestureRecognizer();
}

/// <summary>
/// Occurs when BindingContext is changed: used to initialise the Gesture Recognizers.
/// </summary>
/// <param name="sender">The sender object.</param>
/// <param name="e">The event parameters.</param>
private void AssociatedObjectBindingContextChanged(object sender, EventArgs e)
{
    _parent = _associatedObject.Parent as ContentView;
    _parent?.GestureRecognizers.Remove(_panGestureRecognizer);
    _parent?.GestureRecognizers.Add(_panGestureRecognizer);
}

And subscribed to the PanUpdated event in order to apply the translate transform:

/// <summary>
/// Initialise the events.
/// </summary>
private void InitializeEvents()
{
    CleanupEvents();

    _panGestureRecognizer.PanUpdated += OnPanUpdated;
}

The implementation of this event handler permits to update the X and Y coordinates of the element when a Pan gesture is detected:

/// <summary>
/// Implements Pan/Translate.
/// </summary>
/// <param name="sender">The sender object.</param>
/// <param name="e">The event parameters.</param>
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
    if (_parent == null)
    {
        return;
    }

    if (!IsTranslateEnabled)
    {
        return;
    }

    switch (e.StatusType)
    {
        case GestureStatus.Running:
            _parent.Content.TranslationX = _xOffset + e.TotalX;
            _parent.Content.TranslationY = _yOffset + e.TotalY;
            break;

        case GestureStatus.Completed:
            _xOffset = _parent.Content.TranslationX;
            _yOffset = _parent.Content.TranslationY;
            break;
    }
}

Here we go: the sample app can now be deployed to the emulators and iOS / Android / Windows devices.

Just a couple of notes:

  • deployment to iOS required this workaround to work properly since the new sample app uses different assemblies;
  • Project has been updated to Visual Studio 2019 and Xamarin.Forms 3.6.0.

About

Multi-Touch XAML Behaviors implementing Multi-Touch Manipulation (Gestures) and Inertia.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages