'Swipe Down To Close Popup not working with CarouselView in Xamarin

I am displaying a CarouselView inside a PopupPage (using Rg.Plugins.Popup). It has 2 problems that I don't understand yet:

1. I am trying to do Swipe Down To Close Popup feature. Everything works fine if my UI is just like this:

PopupOne.xaml

<popup:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
            xmlns:popup="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
            xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup"
            .....
            x:Class="xxx.Views.PopupImgProd">
        <ContentView>
            <ContentView.Behaviors>
                <behavior:SwipeDownToClosePopupPage CloseAction="SwipeDownToClosePopupPage_CloseAction"
                                                    ClosingEdge="0"
                                                    ClosingTimeInMs="400"/>            
            </ContentView.Behaviors>
            <StackLayout HorizontalOptions="FillAndExpand" Padding="0" BackgroundColor="#fff">   
                <AbsoluteLayout HorizontalOptions="FillAndExpand">
                    <Frame>
                        ....
                    </Frame>
                    <Frame>
                        ....
                    </Frame>
                </AbsoluteLayout>           
                <Label Text="sss"/>
            </StackLayout>
        </ContentView>    
    </popup:PopupPage>

SwipeDownToClosePopupPage.cs

public class SwipeDownToClosePopupPage : Behavior<View>
{
    private PanGestureRecognizer PanGestureRecognizer { get; set; }
    private DateTimeOffset? StartPanDownTime { get; set; }
    private DateTimeOffset? EndPanDownTime { get; set; }
    private double TotalY { get; set; }
    private bool ReachedEdge { get; set; }
    /// <summary>
    /// Close action, depends on your navigation mode
    /// </summary>
    public event Action CloseAction;

    public static readonly BindableProperty ClosingEdgeProperty = BindableProperty.Create(propertyName: nameof(ClosingEdge)
                                                                                     , returnType: typeof(Double)
                                                                                     , declaringType: typeof(SwipeDownToClosePopupPage)
                                                                                     , defaultValue: Convert.ToDouble(100)
                                                                                     , defaultBindingMode: BindingMode.TwoWay
                                                                                     , propertyChanged: ClosingEdgePropertyChanged);
    /// <summary>
    /// The height from the bottom that will trigger close page 
    /// </summary>
    public Double ClosingEdge
    {
        get { return (Double)GetValue(ClosingEdgeProperty); }
        set { SetValue(ClosingEdgeProperty, Convert.ToDouble(value)); }
    }

    private static void ClosingEdgePropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var control = (SwipeDownToClosePopupPage)bindable;
        if (newValue != null)
        {
            control.ClosingEdge = Convert.ToDouble(newValue);
        }
    }


    public static readonly BindableProperty ClosingTimeInMsProperty = BindableProperty.Create(propertyName: nameof(ClosingTimeInMs)
                                                                                    , returnType: typeof(Int64)
                                                                                    , declaringType: typeof(SwipeDownToClosePopupPage)
                                                                                    , defaultValue: Convert.ToInt64(500)
                                                                                    , defaultBindingMode: BindingMode.TwoWay
                                                                                    , propertyChanged: ClosingTimeInMsPropertyChanged);
    /// <summary>
    /// Scroll time less than this value will trigger close page
    /// </summary>
    public Int64 ClosingTimeInMs
    {
        get { return (Int64)GetValue(ClosingTimeInMsProperty); }
        set { SetValue(ClosingTimeInMsProperty, Convert.ToInt64(value)); }
    }

    private static void ClosingTimeInMsPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var control = (SwipeDownToClosePopupPage)bindable;
        if (newValue != null)
        {
            control.ClosingTimeInMs = Convert.ToInt64(newValue);
        }
    }


    public SwipeDownToClosePopupPage()
    {
        this.PanGestureRecognizer = new PanGestureRecognizer();
    }

    protected override void OnAttachedTo(View v)
    {
        PanGestureRecognizer.PanUpdated += Pan_PanUpdated;
        v.GestureRecognizers.Add(this.PanGestureRecognizer);
        base.OnAttachedTo(v);
    }

    protected override void OnDetachingFrom(View v)
    {
        PanGestureRecognizer.PanUpdated -= Pan_PanUpdated;
        v.GestureRecognizers.Remove(this.PanGestureRecognizer);
        base.OnDetachingFrom(v);
    }

    private void Pan_PanUpdated(object sender, PanUpdatedEventArgs e)
    {
        View v = sender as View;
        switch (e.StatusType)
        {
            case GestureStatus.Started:
                StartPanDownTime = DateTime.Now;
                break;

            case GestureStatus.Running:
                TotalY = e.TotalY;
                if (TotalY > 0)
                {
                    if (Device.RuntimePlatform == Device.Android)
                    {
                        v.TranslateTo(0, TotalY + v.TranslationY, 20, Easing.Linear);
                        //Too close to edge?
                        ReachedEdge = TotalY + v.TranslationY > v.Height - ClosingEdge;
                    }

                    else
                    {
                        v.TranslateTo(0, TotalY, 20, Easing.Linear);
                        //Too close to edge?
                        ReachedEdge = TotalY > v.Height - ClosingEdge;
                    }
                }
                break;

            case GestureStatus.Completed:
                EndPanDownTime = DateTimeOffset.Now;
                if (TotalY > 0
                    || ReachedEdge)
                    //Swipe too fast
                    CloseAction?.Invoke();
                else
                {
                    v.TranslateTo(0, 0, 20, Easing.Linear);
                }
                break;
        }

        if (e.StatusType == GestureStatus.Completed || e.StatusType == GestureStatus.Canceled)
        {
            StartPanDownTime = null;
            EndPanDownTime = null;
        }
    }
}

----------> The above it works great. When I SwipeDown it closes the Popup. Very good

However, now what I display is: CarouselView. The problem occurs here: When I SwipeDown it doesn't close the Popup? Even though I have wrapped the event for it as it was at the beginning.

PopupOne.xaml

<popup:PopupPage xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:popup="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
        xmlns:animations="clr-namespace:Rg.Plugins.Popup.Animations;assembly=Rg.Plugins.Popup"
        .....
        x:Class="TopSell.Views.PopupImgProd">
    <ContentView>
        <ContentView.Behaviors>
            <behavior:SwipeDownToClosePopupPage CloseAction="SwipeDownToClosePopupPage_CloseAction"
                                                ClosingEdge="0"
                                                ClosingTimeInMs="400"/>            
        </ContentView.Behaviors>
        <StackLayout HorizontalOptions="FillAndExpand" Padding="0" BackgroundColor="#fff">       
            <AbsoluteLayout HorizontalOptions="FillAndExpand">
                <Frame>
                    ....
                </Frame>
                <Frame>
                    ....
                </Frame>
            </AbsoluteLayout>           
            <CarouselView x:Name="_stdata" ItemsSource="{Binding imglistProd}">
                <CarouselView.ItemTemplate>
                    <DataTemplate>
                        <StackLayout Padding="0" Margin="0" VerticalOptions="FillAndExpand" x:DataType="model:ProductImages">
                            <Image Aspect="AspectFill" VerticalOptions="CenterAndExpand" Source="{Binding Images}"/>
                        </StackLayout>
                    </DataTemplate>
                </CarouselView.ItemTemplate>
            </CarouselView>
        </StackLayout>
    </ContentView>    
</popup:PopupPage>

PopupOne.xaml.cs

private void SwipeDownToClosePopupPage_CloseAction()
{
    PopupNavigation.Instance.PopAllAsync();
}

---> Is there a conflict between the left and right movement of CarouselView and SwipeDown

2. The displayed image of the CarouselView seems to cut off the top and bottom of the image (Image is cropped when I put it in CarouselView )

enter image description here

Looking forward to everyone's help. Thank you



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source