Skip to content
Open
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
120 changes: 82 additions & 38 deletions src/Calendar.Plugin/Android/SwipeAwareContainerRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,74 +5,118 @@
using Xamarin.Plugin.Calendar.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using View = Xamarin.Forms.View;

[assembly: ExportRenderer(typeof(SwipeAwareContainer), typeof(SwipeAwareContainerRenderer))]
namespace Xamarin.Plugin.Calendar.Android
{
internal class SwipeAwareContainerRenderer : ViewRenderer, GestureDetector.IOnGestureListener
internal class SwipeAwareContainerRenderer : ViewRenderer
{
private const int SwipeDistanceThreshold = 50;
private const int SwipeVelocityThreshold = 20;
private readonly GestureDetector _gestureDetector;
private GestureDetector _gestureDetector;
private GestureDetector.IOnGestureListener _gestureListener;
private bool _isDisposed;

public SwipeAwareContainerRenderer(Context context) : base(context)
{
_gestureDetector = new GestureDetector(context, this);
}

protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);

if (e.OldElement != null)
{
DisposeGestureDetectorAndListener();
}

if (e.NewElement != null)
{
_gestureListener = new InnerGestureListener(Element as SwipeAwareContainer);
_gestureDetector = new GestureDetector(Context, _gestureListener);
}
}

public override bool OnInterceptTouchEvent(MotionEvent ev)
{
if (_isDisposed)
return false;

if (Element is SwipeAwareContainer element && !element.SwipeDetectionDisabled)
_gestureDetector.OnTouchEvent(ev);
_gestureDetector?.OnTouchEvent(ev);

return base.OnInterceptTouchEvent(ev);
}

public bool OnFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
protected override void Dispose(bool disposing)
{
if (!(Element is SwipeAwareContainer element))
return false;
if (_isDisposed)
return;

float distanceX = e2.GetX() - e1.GetX();
float distanceY = e2.GetY() - e1.GetY();
_isDisposed = true;

if (Math.Abs(distanceX) > Math.Abs(distanceY))
if (disposing)
{
if (Math.Abs(distanceX) > SwipeDistanceThreshold && Math.Abs(velocityX) > SwipeVelocityThreshold)
{
if (distanceX > 0)
element.OnSwipeRight();
else
element.OnSwipeLeft();

return true;
}
DisposeGestureDetectorAndListener();
}
else
{
if (Math.Abs(distanceY) > SwipeDistanceThreshold && Math.Abs(velocityY) > SwipeVelocityThreshold)
{
if (distanceY > 0)
element.OnSwipeDown();
else
element.OnSwipeUp();

return true;
}
}
base.Dispose(disposing);
}

private void DisposeGestureDetectorAndListener()
{
_gestureDetector?.Dispose();
_gestureDetector = null;

return false;
_gestureListener?.Dispose();
_gestureListener = null;
}

#region Unused gestures
private class InnerGestureListener : GestureDetector.SimpleOnGestureListener
{
private SwipeAwareContainer SwipeAwareContainer { get; }

public InnerGestureListener(SwipeAwareContainer swipeAwareContainer)
{
SwipeAwareContainer = swipeAwareContainer;
}

public override bool OnFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
if (SwipeAwareContainer == null)
return false;

float distanceX = e2.GetX() - e1.GetX();
float distanceY = e2.GetY() - e1.GetY();

public bool OnDown(MotionEvent e) => false;
public void OnLongPress(MotionEvent e) { }
public bool OnScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) => false;
public void OnShowPress(MotionEvent e) { }
public bool OnSingleTapUp(MotionEvent e) => false;
if (Math.Abs(distanceX) > Math.Abs(distanceY))
{
if (Math.Abs(distanceX) > SwipeDistanceThreshold && Math.Abs(velocityX) > SwipeVelocityThreshold)
{
if (distanceX > 0)
SwipeAwareContainer.OnSwipeRight();
else
SwipeAwareContainer.OnSwipeLeft();

#endregion
return true;
}
}
else
{
if (Math.Abs(distanceY) > SwipeDistanceThreshold && Math.Abs(velocityY) > SwipeVelocityThreshold)
{
if (distanceY > 0)
SwipeAwareContainer.OnSwipeDown();
else
SwipeAwareContainer.OnSwipeUp();

return true;
}
}

return false;
}
}
}
}