5

I have the following XAML. I want to target phones with a scrollview, and want scrolling disabled on a tablet.

 <ScrollView InputTransparent="False" Orientation="Both" >

            <ScrollView.IsEnabled>
                <OnIdiom x:TypeArguments="x:Boolean">

                    <OnIdiom.Phone>True</OnIdiom.Phone>
                    <OnIdiom.Tablet>True</OnIdiom.Tablet>
                </OnIdiom>
            </ScrollView.IsEnabled>

    <StackLayout VerticalOptions="FillAndExpand" BackgroundColor="White" >
                <StackLayout.HorizontalOptions>
                    <OnIdiom x:TypeArguments="LayoutOptions">
                        <OnIdiom.Tablet>FillAndExpand</OnIdiom.Tablet>
                        <OnIdiom.Phone>Start</OnIdiom.Phone>
                    </OnIdiom>

                </StackLayout.HorizontalOptions>

                <Grid BackgroundColor="White" HeightRequest="65" MinimumHeightRequest="65">
                    <Grid.HorizontalOptions>
                        <OnIdiom x:TypeArguments="LayoutOptions">
                            <OnIdiom.Tablet>CenterAndExpand</OnIdiom.Tablet>
                            <OnIdiom.Phone>Start</OnIdiom.Phone>
                        </OnIdiom>

                    </Grid.HorizontalOptions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition  Width="Auto"  />
                    </Grid.ColumnDefinitions>
                    <WebView x:Name="webViewBtn1" HeightRequest="65" Grid.Column="0" Grid.ColumnSpan="1"  VerticalOptions="FillAndExpand" BackgroundColor="White">
                    <WebView.HorizontalOptions>
                        <OnIdiom x:TypeArguments="LayoutOptions">
                            <OnIdiom.Tablet>CenterAndExpand</OnIdiom.Tablet>
                            <OnIdiom.Phone>Start</OnIdiom.Phone>
                        </OnIdiom>
                    </WebView.HorizontalOptions>
                        <WebView.WidthRequest>
                            <OnIdiom x:TypeArguments="x:Double">
                                <OnIdiom.Tablet>770</OnIdiom.Tablet>
                                <OnIdiom.Phone>300</OnIdiom.Phone>

                            </OnIdiom>

                        </WebView.WidthRequest>
                    </WebView>
                    <Button Grid.Column="0" Grid.ColumnSpan="1" x:Name="btn1" Clicked="btn1_Clicked" BackgroundColor="Transparent" TextColor="Transparent"  BorderColor="White" />
                </Grid>
    </StackLayout>
        </ScrollView>

the buttons no longer allow the user to click on them if I set ScrollView.IsEnabled the following way:

  <OnIdiom.Tablet>False</OnIdiom.Tablet>

My assumption that using InputTransparent was not correct. Is there a way to make the buttons clickable inside a scroll view that has scrolling disabled?

I essentially am looking for something like Orientation=None, but that is not an option.

1
  • If the content of the scrollview fits within the bounds of the scrollview, scrolling will be disabled by default anyway, so there's no reason to differentiate between phone and tablet. Commented Oct 20, 2018 at 1:36

4 Answers 4

8

You need to write a CustomRenderer for disabling the scroll.

On iOS UIScrollView has a ScrollEnabled property

protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
    base.OnElementChanged(e);
    // IsScrollEnabled just a custom property
    // handled it in OnPropertyChanged too
    ScrollEnabled = Element.IsScrollEnabled;
}

Android it is a bit tricky, there is not direct property. We intercept the touch event and return without handling it.

public override bool OnInterceptTouchEvent(MotionEvent ev)
{
    if (Element.IsScrollEnabled)
    {
        return base.OnInterceptTouchEvent(ev);
    }
    else
    {
        return false;
    }
}

public override bool OnTouchEvent(MotionEvent ev)
{
    if (Element.IsScrollEnabled)
    {
        return base.OnTouchEvent(ev);
    }
    else
    {
        return false;
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

The solution for iOS is awesome, thanks! Can we, on android, distinguish between touch events for scrolling and for tapping child buttons?
I haven't tried it yet but, the touch event should pass through all the containing elements.
It does propagate to the child elements, but it also does still scroll. At least it does for me. returning true instead of false in OnTouchEvent does not seem to affect that. Returning true from OnInterceptTouchEvent does stop the scrolling from happening, but also blocks the children.
5

In the latest version of Xamarin Forms, you can set the Orientation to Neither.

scrollV.Orientation = ScrollOrientation.Neither;

7 Comments

It makes my scrollview jump to the top. Any ideas?
Try to set it in the initialization of the page. Is this applicable in your case?
sadly but no. I want to disable it temporary while moving some points on a chart. And the user can be on any scroll position at the moment
ok. another workaround would be to add a transparent view above the whole scrollview which will be only visible if the chart is animating
Hm. It gave me a good idea. Thank you very much. Really. Yes, the overlay can solve it in this kind of way.
|
4

I ended up using this approach to disable vertical scrolling on an iPad, which is my target device. Not perfect for android 7 inch tablets, but oh well:

            <ScrollView.Orientation>
                <OnPlatform x:TypeArguments="ScrollOrientation">
                    <On Platform="iOS">
                        <OnIdiom x:TypeArguments="ScrollOrientation">
                            <OnIdiom.Phone>Both</OnIdiom.Phone>
                            <OnIdiom.Tablet>Horizontal</OnIdiom.Tablet>
                        </OnIdiom>
                    </On>
                    <On Platform="Android">
                        <OnIdiom x:TypeArguments="ScrollOrientation">
                            <OnIdiom.Phone>Both</OnIdiom.Phone>
                            <OnIdiom.Tablet>Both</OnIdiom.Tablet>
                        </OnIdiom>
                    </On>
                    <On Platform="UWP">Both</On>
                </OnPlatform>
            </ScrollView.Orientation>

Comments

1

Cool and compact way to disable scrolling in Xamarin Forms without affecting it's children through ScrollEnabled extension method:

public static class ScrollViewEx
{
    /// <summary>
    /// Disables scrollview by modifying Scrolled Event and attaching itself to ScrollView's binding context
    /// Scrolled event sends it back to the original x,y
    /// </summary>
    public class DisabledScrollClass : IDisposable
    {
        private double ScrollX;
        private double ScrollY;
        private object OldContext;
        private ScrollView Parent;

        public DisabledScrollClass(ScrollView parent)
        {
            Parent = parent;
            ScrollX = parent.ScrollX;
            ScrollY = parent.ScrollY;
            OldContext = parent.BindingContext;
            parent.Scrolled += Scrolled;
            parent.BindingContext = this;
        }

        private void Scrolled(object sender, ScrolledEventArgs e)
        {
            (sender as ScrollView)?.ScrollToAsync(ScrollX, ScrollY, false);
        }

        public void Dispose()
        {
            Parent.Scrolled -= Scrolled;
            Parent.BindingContext = OldContext;
        }
    }

    public static ScrollView ScrollEnabled(this ScrollView scroll, bool isEnabled)
    {
        DisabledScrollClass binding = scroll.BindingContext as DisabledScrollClass;
        if (isEnabled && binding != null)
            binding.Dispose();
        if (!isEnabled && binding == null)
            _ = new DisabledScrollClass(scroll);
        return scroll;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.