Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add gestures events to View #39

Merged
merged 3 commits into from
Sep 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}
}
}