Forum Xamarin.iOS
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

CarouselView with a ScrollView with a SwipeView

smallwiresmallwire Member ✭✭
edited February 5 in Xamarin.iOS

Hello Xamarin community,

I have a CarouselView, with different templates per slide (set via a DataTemplateSelector), both of which having a ScrollView.

On iOS, after starting to swipe horizontally, the CarouselView's content can be dragged vertically too. (Interestingly, this stops happening if I trigger the hot reload.)

I switched to CarouselView from a CarouselPage, for which I solved this problem with a CarouselPageRenderer, by setting ContentInsetAdjustmentBehavior to UIScrollViewContentInsetAdjustmentBehavior.Never for all View.Subviews.OfType<UIScrollView>().

One of the ScrollViews contains a SwipeView with TopItems. It works fine on Android, but not at all on iOS.

Any ideas on how to address these issues?

Thanks!

Best Answer

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    This is caused by the conflict of the scrolling between your swipe view and scroll view.
    I tried to add a custom renderer for the scroll view like:

    [assembly: ExportRenderer(typeof(ScrollView), typeof(CustomScrollviewRenderer))]
    namespace CarouselViewScrollSwipe.iOS
    {
        public class CustomScrollviewRenderer : ScrollViewRenderer
        {
            CGRect frame = default(CGRect);
            public override void Draw(CGRect rect)
            {
                base.Draw(rect);
    
                foreach (UIView view in Subviews.FirstOrDefault().Subviews)
                {
                    if (view is SwipeViewRenderer)
                    {
                        frame = view.Frame;
                        break;
                    }
                }
            }
    
            public override void TouchesBegan(NSSet touches, UIEvent evt)
            {
                base.TouchesBegan(touches, evt);
    
                UITouch touch = touches.AnyObject as UITouch;
                var point = touch.LocationInView(this);
                if (frame.Contains(point))
                {
                    ScrollEnabled = false;
                }
            }
            public override void TouchesEnded(NSSet touches, UIEvent evt)
            {
                base.TouchesEnded(touches, evt);
    
                ScrollEnabled = true;
            }
        }
    }
    

    The swipe view could be dragged now. However, I still don't recommend to put a vertical swiping view into a vertical orientation scroll view. They could be both dragged in the vertical direction and it will raise bad user experience.

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    contentInsetAdjustmentBehavior determines whether the content of the UIScrollView will automatically adjust its content depending on the safe area.
    If you set it to never the content will be overlapped by the top notch.
    What do you mean about the SwipeView won't work on iOS?
    Could you provide a basic repo to help us reproduce this issue?

  • smallwiresmallwire Member ✭✭

    The problem (and where I previously got the solution from, before switching the CarouselPage to CarouselView) is similar to here: https://forums.xamarin.com/discussion/104385/ios-11-carousel-page-issues

    I hope the screenshots there give you a better understanding of the issue. Otherwise, I will create a proof-of-concept app.

    On iOS the SwipeView simply doesn't open when I swipe its content. Instead, the whole view is dragged downwards.

    The markup:

    <CarouselView>
        <ContentView.Content>
            <StackLayout>
                <ScrollView>
                    <StackLayout>
                        <SwipeView>
                            <SwipeView.TopItems>
    
                            </SwipeView.TopItems>
                            <StackLayout>
                                <!-- Dragging downwards here should reveal the SwipeView.TopItems, but only works on Android -->
                            </StackLayout>
                        </SwipeView>
                    </StackLayout>
                </ScrollView>
            </StackLayout>
        </ContentView.Content>
    </CarouselView>
    
  • smallwiresmallwire Member ✭✭

    I made a proof-of-concept app, and, interestingly, the problem where the whole CarouselView can be dragged downwards doesn't happen. I haven't yet figured out why that issue occurs in my "real" app.

    But the SwipeView doesn't work on iOS while working fine on Android.

  • LandLuLandLu Member, Xamarin Team Xamurai
    Accepted Answer

    This is caused by the conflict of the scrolling between your swipe view and scroll view.
    I tried to add a custom renderer for the scroll view like:

    [assembly: ExportRenderer(typeof(ScrollView), typeof(CustomScrollviewRenderer))]
    namespace CarouselViewScrollSwipe.iOS
    {
        public class CustomScrollviewRenderer : ScrollViewRenderer
        {
            CGRect frame = default(CGRect);
            public override void Draw(CGRect rect)
            {
                base.Draw(rect);
    
                foreach (UIView view in Subviews.FirstOrDefault().Subviews)
                {
                    if (view is SwipeViewRenderer)
                    {
                        frame = view.Frame;
                        break;
                    }
                }
            }
    
            public override void TouchesBegan(NSSet touches, UIEvent evt)
            {
                base.TouchesBegan(touches, evt);
    
                UITouch touch = touches.AnyObject as UITouch;
                var point = touch.LocationInView(this);
                if (frame.Contains(point))
                {
                    ScrollEnabled = false;
                }
            }
            public override void TouchesEnded(NSSet touches, UIEvent evt)
            {
                base.TouchesEnded(touches, evt);
    
                ScrollEnabled = true;
            }
        }
    }
    

    The swipe view could be dragged now. However, I still don't recommend to put a vertical swiping view into a vertical orientation scroll view. They could be both dragged in the vertical direction and it will raise bad user experience.

  • smallwiresmallwire Member ✭✭

    Thanks LandLu! I appreciate your help!

    It works, but I think you are right about a potentially bad UX. I will assess different approaches to showing the swipe view's content.

Sign In or Register to comment.