Skip to content

Commit

Permalink
Add gestures events to View (#39)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dreamescaper authored Sep 17, 2022
1 parent 301d029 commit 05e1e83
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 2 deletions.
4 changes: 3 additions & 1 deletion samples/ControlGallery/AppShell.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
@using ControlGallery.Views.Collections
@using ControlGallery.Views.Collections.CollectionView
@using ControlGallery.Views.EditText
@using ControlGallery.Views.Gestures
@using ControlGallery.Views.InitiateCommands
@using ControlGallery.Views.Layouts
@using ControlGallery.Views.PresentData
Expand Down Expand Up @@ -51,6 +52,7 @@
<ShellItemsPage />

@*Other*@
<GesturesPage />
<SkiaCanvasPage />
<GestureEvents />
<GestureRecognizersPage />
</Shell>
28 changes: 28 additions & 0 deletions samples/ControlGallery/Views/Gestures/GestureEvents.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@using System.Collections.ObjectModel

<ContentPage Title="Gesture Events">
<VerticalStackLayout>
<Label>Try tapping, double tapping, or swiping items.</Label>
<Button Text="Add" OnClick="AddItem" />
@foreach (var item in _items)
{
<GestureItem @key="item" Item="item" OnRemoving="RemoveItem" />
}
</VerticalStackLayout>
</ContentPage>


@code {
List<int> _items = new(Enumerable.Range(0, 10));

void RemoveItem(int i)
{
_items.Remove(i);
}

void AddItem()
{
var i = _items.DefaultIfEmpty(0).Max() + 1;
_items.Add(i);
}
}
43 changes: 43 additions & 0 deletions samples/ControlGallery/Views/Gestures/GestureItem.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<Frame @ref="_element" BackgroundColor="Colors.LightCyan" CornerRadius="7" Padding="20" Margin="4"
OnTap="OnTap"
OnDoubleTap="OnDoubleTap"
OnPanUpdate="OnPanUpdate">

<Label TextColor="Colors.Black">@Item - @status</Label>
</Frame>

@code {
[Parameter] public int Item { get; set; }
[Parameter] public EventCallback<int> OnRemoving { get; set; }

Frame _element;
string status = "Pending";
double _lastX;

void OnTap() => status = "Tapped";
void OnDoubleTap() => status = "Double Tapped";

async Task OnPanUpdate(PanUpdatedEventArgs args)
{
if (args.StatusType == GestureStatus.Running)
{
_lastX = args.TotalX;
_element.NativeControl.TranslationX = args.TotalX;
}
else if (args.StatusType == GestureStatus.Completed)
{
if (Math.Abs(_lastX) > 50)
{
var screenWidth = DeviceDisplay.MainDisplayInfo.Width;

var translateTo = Math.Sign(_lastX) * screenWidth;
await _element.NativeControl.TranslateTo(translateTo, 0);
await OnRemoving.InvokeAsync(Item);
}
else
{
_element.NativeControl.TranslationX = args.TotalX;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@page "/gestureplayground"

<ContentPage Title="Gestures">
<ContentPage Title="Gesture Recognizers">
<StackLayout Margin="new Thickness(20)">

<Label Text="Tap me or pan me"
Expand Down
160 changes: 160 additions & 0 deletions src/BlazorBindings.Maui/Elements/View.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

using Microsoft.AspNetCore.Components;
using Microsoft.Maui.Controls;
using System;
using System.Linq;
using MC = Microsoft.Maui.Controls;

namespace BlazorBindings.Maui.Elements
{
public abstract partial class View : VisualElement
{
[Parameter] public EventCallback OnTap { get; set; }
[Parameter] public EventCallback OnDoubleTap { get; set; }
[Parameter] public EventCallback<SwipedEventArgs> OnSwipe { get; set; }
[Parameter] public EventCallback<PinchGestureUpdatedEventArgs> OnPinchUpdate { get; set; }
[Parameter] public EventCallback<PanUpdatedEventArgs> OnPanUpdate { get; set; }

protected override bool HandleAdditionalParameter(string name, object value)
{
switch (name)
{
case nameof(OnTap):
if (!Equals(value, OnTap))
{
HandleTap();
OnTap = (EventCallback)value;
}
return true;

case nameof(OnDoubleTap):
if (!Equals(value, OnDoubleTap))
{
HandleDoubleTap();
OnDoubleTap = (EventCallback)value;
}
return true;

case nameof(OnSwipe):
if (!Equals(value, OnSwipe))
{
HandleSwipe();
OnSwipe = (EventCallback<SwipedEventArgs>)value;
}
return true;

case nameof(OnPinchUpdate):
if (!Equals(value, OnPinchUpdate))
{
HandlePinch();
OnPinchUpdate = (EventCallback<PinchGestureUpdatedEventArgs>)value;
}
return true;

case nameof(OnPanUpdate):
if (!Equals(value, OnPanUpdate))
{
HandlePan();
OnPanUpdate = (EventCallback<PanUpdatedEventArgs>)value;
}
return true;

default:
return base.HandleAdditionalParameter(name, value);

}
}

private void HandleTap()
{
void GestureRecognizerTapped(object sender, EventArgs e) => OnTap.InvokeAsync();

var tapGestureRecognizer = NativeControl.GestureRecognizers
.OfType<MC.TapGestureRecognizer>()
.FirstOrDefault(gr => gr.NumberOfTapsRequired == 1);

if (tapGestureRecognizer is null)
{
tapGestureRecognizer = new MC.TapGestureRecognizer();
NativeControl.GestureRecognizers.Add(tapGestureRecognizer);
}

tapGestureRecognizer.Tapped -= GestureRecognizerTapped;
tapGestureRecognizer.Tapped += GestureRecognizerTapped;
}

private void HandleDoubleTap()
{
void GestureRecognizerTapped(object sender, EventArgs e) => OnDoubleTap.InvokeAsync();

var tapGestureRecognizer = NativeControl.GestureRecognizers
.OfType<MC.TapGestureRecognizer>()
.FirstOrDefault(gr => gr.NumberOfTapsRequired == 2);

if (tapGestureRecognizer is null)
{
tapGestureRecognizer = new MC.TapGestureRecognizer { NumberOfTapsRequired = 2 };
NativeControl.GestureRecognizers.Add(tapGestureRecognizer);
}

tapGestureRecognizer.Tapped -= GestureRecognizerTapped;
tapGestureRecognizer.Tapped += GestureRecognizerTapped;
}

private void HandleSwipe()
{
void GestureRecognizerSwiped(object sender, SwipedEventArgs e) => OnSwipe.InvokeAsync(e);

var swipeGestureRecognizer = NativeControl.GestureRecognizers
.OfType<MC.SwipeGestureRecognizer>()
.FirstOrDefault();

if (swipeGestureRecognizer is null)
{
swipeGestureRecognizer = new MC.SwipeGestureRecognizer();
NativeControl.GestureRecognizers.Add(swipeGestureRecognizer);
}

swipeGestureRecognizer.Swiped -= GestureRecognizerSwiped;
swipeGestureRecognizer.Swiped += GestureRecognizerSwiped;
}

private void HandlePinch()
{
void GestureRecognizerPinchUpdated(object sender, PinchGestureUpdatedEventArgs e) => OnPinchUpdate.InvokeAsync(e);

var pinchGestureRecognizer = NativeControl.GestureRecognizers
.OfType<MC.PinchGestureRecognizer>()
.FirstOrDefault();

if (pinchGestureRecognizer is null)
{
pinchGestureRecognizer = new MC.PinchGestureRecognizer();
NativeControl.GestureRecognizers.Add(pinchGestureRecognizer);
}

pinchGestureRecognizer.PinchUpdated -= GestureRecognizerPinchUpdated;
pinchGestureRecognizer.PinchUpdated += GestureRecognizerPinchUpdated;
}

private void HandlePan()
{
void GestureRecognizerPanUpdated(object sender, PanUpdatedEventArgs e) => OnPanUpdate.InvokeAsync(e);

var pinchGestureRecognizer = NativeControl.GestureRecognizers
.OfType<MC.PanGestureRecognizer>()
.FirstOrDefault();

if (pinchGestureRecognizer is null)
{
pinchGestureRecognizer = new MC.PanGestureRecognizer();
NativeControl.GestureRecognizers.Add(pinchGestureRecognizer);
}

pinchGestureRecognizer.PanUpdated -= GestureRecognizerPanUpdated;
pinchGestureRecognizer.PanUpdated += GestureRecognizerPanUpdated;
}
}
}

0 comments on commit 05e1e83

Please sign in to comment.