I'm working on a Custom View
on .net MAUI
.
In this Custom View
, I would like to load an Image
and be able to move it around the screen using Pan Gesture
recognizer.
I was following this tutorial. As first step, I'm just using a Border
to test the behaviour.
This is my custom control:
SignatureView.xaml.cs
public partial class SignatureView : ContentView
{
private double panX;
private double panY;
public SignatureView()
{
InitializeComponent();
}
private void PanGestureRecognizer_PanUpdated(object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Running:
double boundsX = Signature.Width;
double boundsY = Signature.Height;
Signature.TranslationX = Math.Clamp(panX + e.TotalX, -boundsX, boundsX);
Signature.TranslationY = Math.Clamp(panY + e.TotalY, -boundsY, boundsY);
break;
case GestureStatus.Completed:
panX = Signature.TranslationX;
panY = Signature.TranslationY;
break;
}
}
}
SignatureView.xaml
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.Controls.SignatureView">
<AbsoluteLayout BackgroundColor="White">
<Border x:Name="Signature" StrokeShape="RoundRectangle 50" BackgroundColor="Blue" HeightRequest="50" WidthRequest="50">
<Border.GestureRecognizers>
<PanGestureRecognizer PanUpdated="PanGestureRecognizer_PanUpdated"/>
</Border.GestureRecognizers>
</Border>
</AbsoluteLayout>
<ContentView/>
This is how I'm using this control:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:MyApp.Controls"
x:Class="MyApp.Views.MyPage">
<ContentPage.Content>
<controls:SignatureView/>
</ContentPage.Content>
</ContentPage>
This is the behaviour I'm seeing:
Am I doing something wrong? How could I smoothly move the view around?
You may make some changes to PanGestureRecognizer_PanUpdated
to handle pan gesture for MAUI android. Actually, it needs some calculation when moving the Border
to make it always inside the AbsoluteLayout
. You may try the following code,
private void PanGestureRecognizer_PanUpdated(object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Started:
break;
case GestureStatus.Running:
var parent = Signature.Parent as AbsoluteLayout;
//control the x-axis direction move
if (Signature.TranslationX + Signature.Width + e.TotalX <= parent.Width & Signature.TranslationX + e.TotalX >= 0)
{
Signature.TranslationX += e.TotalX;
}
else if (Signature.TranslationX + Signature.Width + e.TotalX > parent.Width)
{
Signature.TranslationX = parent.Width - Signature.Width;
}
else
{
Signature.TranslationX = 0;
}
//control the y-axis direction move
if (Signature.TranslationY + Signature.Height + e.TotalY <= parent.Height & Signature.TranslationY + e.TotalY >= 0)
{
Signature.TranslationY += e.TotalY;
}
else if(Signature.TranslationY + Signature.Height + e.TotalY > parent.Height)
{
Signature.TranslationY = parent.Height - Signature.Height;
}
else
{
Signature.TranslationY = 0;
}
break;
case GestureStatus.Completed:
break;
}
}
Futhermore, if you want to set a Padding
for AbsoluteLayout
, such like,
public SignatureView()
{
InitializeComponent();
myAbsoluteLayout.Padding = new Thickness(20, 20, 20, 20);
}
Then the calculation might be more complex. Because you have to take the Padding
size into consideration when moving. Here is an example to achieve this,
private void PanGestureRecognizer_PanUpdated(object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Started:
break;
case GestureStatus.Running:
var parent = Signature.Parent as AbsoluteLayout;
//control the x-axis direction move
if (Signature.TranslationX + Signature.Width + e.TotalX + parent.Padding.Left + parent.Padding.Right <= parent.Width &
Signature.TranslationX + e.TotalX - parent.Padding.Left >= 0)
{
Signature.TranslationX += e.TotalX;
}
else if (Signature.TranslationX + Signature.Width + e.TotalX + parent.Padding.Left + parent.Padding.Right > parent.Width)
{
Signature.TranslationX = parent.Width - Signature.Width - parent.Padding.Left - parent.Padding.Right;
}
else
{
Signature.TranslationX = 0;
}
//control the y-axis direction move
if (Signature.TranslationY + Signature.Height + e.TotalY + parent.Padding.Top + parent.Padding.Bottom <= parent.Height &
Signature.TranslationY + e.TotalY -parent.Padding.Top >= 0)
{
Signature.TranslationY += e.TotalY;
}
else if(Signature.TranslationY + Signature.Height + e.TotalY + parent.Padding.Top + parent.Padding.Bottom > parent.Height)
{
Signature.TranslationY = parent.Height - Signature.Height - parent.Padding.Top - parent.Padding.Bottom;
}
else
{
Signature.TranslationY = 0;
}
break;
case GestureStatus.Completed:
break;
}
}
Hope it helps!