Open RasikaPalanisamy opened 7 months ago
@RasikaPalanisamy it might be useful to ask this in discussions or StackOverflow to see if there's a way to optimize how you are updating.
We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.
@PureWeen We need the correct PanGestureRecognizerEventArgs.TotalX value. However, the PanGestureRecognizerEventArgs.TotalX value is returning an incorrect value.
Can confirm PanGestureRecognizerEventArgs.TotalX is returning nonsensical value on Android, and needs to be taken out of the backlog
I ran into the same issue and used a workaround for those who are interested. Feel free to provide suggestions for improvement.
private double _lastPanX1 = 0;
private double _lastPanX2 = 0;
private double _lastPanX3 = 0;
private bool IsValidPanEvent(object? sender, PanUpdatedEventArgs e)
{
bool valid = false;
if (e.StatusType == GestureStatus.Started)
{
_lastPanX1 = 0;
_lastPanX2 = 0;
_lastPanX3 = 0;
valid = true;
}
else if (e.StatusType == GestureStatus.Running)
{
var lastPanX4 = _lastPanX3;
_lastPanX3 = _lastPanX2;
_lastPanX2 = _lastPanX1;
_lastPanX1 = e.TotalX;
// detect whether user is increasing or decreasing
// therefore, we will compare 1 with 3 and 2 with 4:
// if different, we expect an invalid call
// due to update speed I see no reason to skip some of the events
bool totalXIncreases1 = _lastPanX1 > _lastPanX3;
bool totalXIncreases2 = _lastPanX2 > lastPanX4;
if (totalXIncreases1 == totalXIncreases2)
{
if (totalXIncreases1)
{
// if we expect increase, we want to make sure, that the new value is actually higher
if (_lastPanX1 > _lastPanX2)
{
valid = true;
}
}
else
{
if (_lastPanX1 < _lastPanX2)
{
valid = true;
}
}
}
}
return valid;
}
Verified this on VS 17.10.0 Preview 2.0(8.0.14). Repro on Android 14.0-API34, not repro on iOS 17.2 and MacCatalyst. Project: CustomSample.zip Android:
Different behavior on Windows 11:
I noticed in src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Android.cs
in OnPlatformViewTouched
, the event consumed boolean value returned from OnTouchEvent
isn't propagated out. The lines
if (e.Event != null)
OnTouchEvent(e.Event);
should be
if (e.Event != null)
e.Handled = OnTouchEvent(e.Event);
I think I've figured it out. It looks like InnerGestureListener
should use RawX
and RawY
instead of GetX()
and GetY()
. The raw versions return absolute screen coordinates, while the non-raw versions return the coordinates relative to the view. If the view is being translated, that shifts the view so the relative coordinates get messed up for calculating the length of the swipe, but the absoulte coordinates would still give the correct length of the swipe.
Here is the workaround I'm using to create smooth panning on Android. I've subclassed PanGestureRecognizer and re-implemented the IPanGestureController. Just be sure to set the PanUpdated handler using either XAML or a variable of the inherited type, due to having to use the new keyword to create an event handler the inherited class can trigger.
internal sealed class CorrectedPanGestureRecognizer : PanGestureRecognizer, IPanGestureController
{
#if ANDROID
// Index 0 is X, index 1 is Y
private readonly int[] startingLocation = new int[2];
private readonly int[] currentLocation = new int[2];
#endif
void IPanGestureController.SendPan(Element sender, double totalX, double totalY, int gestureId)
{
#if ANDROID
ArgumentNullException.ThrowIfNull(sender.Handler.MauiContext?.Context);
Android.Views.View view = sender.ToPlatform(sender.Handler.MauiContext);
view.GetLocationOnScreen(currentLocation);
totalX += sender.Handler.MauiContext.Context.FromPixels(currentLocation[0] - startingLocation[0]);
totalY += sender.Handler.MauiContext.Context.FromPixels(currentLocation[1] - startingLocation[1]);
#endif
PanUpdated?.Invoke(sender, new PanUpdatedEventArgs(GestureStatus.Running, gestureId, totalX, totalY));
}
void IPanGestureController.SendPanCanceled(Element sender, int gestureId)
{
PanUpdated?.Invoke(sender, new PanUpdatedEventArgs(GestureStatus.Canceled, gestureId));
}
void IPanGestureController.SendPanCompleted(Element sender, int gestureId)
{
PanUpdated?.Invoke(sender, new PanUpdatedEventArgs(GestureStatus.Completed, gestureId));
}
void IPanGestureController.SendPanStarted(Element sender, int gestureId)
{
#if ANDROID
ArgumentNullException.ThrowIfNull(sender.Handler.MauiContext);
Android.Views.View view = sender.ToPlatform(sender.Handler.MauiContext);
view.GetLocationOnScreen(startingLocation);
#endif
PanUpdated?.Invoke(sender, new PanUpdatedEventArgs(GestureStatus.Started, gestureId));
}
public new event EventHandler<PanUpdatedEventArgs>? PanUpdated;
}
I've also noticed that if dragging across the whole screen the values returned don't reflect the actual position of the finger/pen. This is only noticeable if dragging a larger distance, feels almost as if it's a factor of 2 out. Again, only on Android.
I was looking into a different pan issue (#24252) and when I tested on Android I came across this problem as well.
The CorrectedPanGestureRecognizer
from BurningLights above does fix the issue for me.
https://github.com/user-attachments/assets/e9ba78c9-c5e6-41e1-8699-e7eb2e54fd26
https://github.com/user-attachments/assets/0bd821e9-0ab8-4dbc-9195-9e46e23994b8
Description
I have created the ContomView, which is derived from CustomLayout. CustomView has 2 children that are derived from contentView. The second child has the PanGestureRecognizer. While the PanGesture is running, I have changed the width of the first child. Now, flickering occurs on the control because the PanGestureRecognizerEventArgs.TotalX value is updated incorrectly.
Steps to Reproduce
1.Run the attached sample.
Observed behavior: flickering occurs on the control.
https://github.com/dotnet/maui/assets/92015119/44dce4bf-6eea-4f54-8e3d-f566606271d7
Link to public reproduction project repository
https://github.com/RasikaPalanisamy/CustomSample
Version with bug
Unknown/Other
Is this a regression from previous behavior?
Not sure, did not test other versions
Last version that worked well
Unknown/Other
Affected platforms
Android, Windows
Affected platform versions
No response
Did you find any workaround?
No response
Relevant log output
No response