Forum Xamarin.Forms
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.

How to use a grid in a scrollview in Xamarin.Forms?

WorldOfBastiWorldOfBasti Member ✭✭✭

Hi, I need to create a Grid in a scroll view. I created a version for the portrait and landscape mode. It should be scrollable in the portrait mode, but not in the landscape mode. The problem is if I add the scrollview it doesn't look like expected in landscape mode. Here is a gif with an example:

Here is my xaml code:

    <ContentPage.Content>
        <ScrollView>
            <Grid x:Name="myLayout" ColumnSpacing="0" RowSpacing="0">
                <BoxView x:Name="box1" BackgroundColor="Green"/>
                <BoxView x:Name="box2" BackgroundColor="Yellow"/>
                <BoxView x:Name="box3" BackgroundColor="Blue"/>
                <BoxView x:Name="box4" BackgroundColor="Gray"/>
            </Grid>
        </ScrollView>
    </ContentPage.Content>

And here the C# code, which handling the Orientation change:

    public partial class myPage : ContentPage
    {
        private double width,
                       height;

        public myPage()
        {
            InitializeComponent();

            width = this.Width;
            height = this.Height;
        }

        protected override void OnSizeAllocated(double width, double height)
        {
            base.OnSizeAllocated(width, height);

            if (this.width != width || this.height != height)
            {
                this.width = width;
                this.height = height;

                UpdateLayout();
            }
        }

        private void UpdateLayout()
        {
            myLayout.ColumnDefinitions.Clear();
            myLayout.RowDefinitions.Clear();
            myLayout.Children.Clear();

            if (width > height) SetLandscapeLayout();
            else SetPortraitLayout();
        }

        private void SetPortraitLayout()
        {
            myLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            myLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            myLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            myLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });

            myLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });
            myLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });

            myLayout.Children.Add(view: box1, left: 0, top: 0);
            box1.HeightRequest = box1.Width;
            myLayout.Children.Add(view: box2, left: 1, top: 0);
            box2.HeightRequest = box2.Width;
            myLayout.Children.Add(view: box3, left: 2, top: 0);
            box3.HeightRequest = box3.Width;
            myLayout.Children.Add(view: box4, left: 3, top: 0);
            box4.HeightRequest = box4.Width;
        }

        private void SetLandscapeLayout()
        {
            myLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
            myLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
            myLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
            myLayout.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });

            myLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
            myLayout.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });

            myLayout.Children.Add(view: box1, left: 0, top: 0);
            box1.WidthRequest = box1.Height;
            myLayout.Children.Add(view: box2, left: 0, top: 1);
            box2.WidthRequest = box2.Height;
            myLayout.Children.Add(view: box3, left: 0, top: 2);
            box3.WidthRequest = box3.Height;
            myLayout.Children.Add(view: box4, left: 0, top: 3);
            box4.WidthRequest = box4.Height;
        }
    }

Thanks in advance.

Best Answer

  • WorldOfBastiWorldOfBasti Member ✭✭✭
    Accepted Answer

    Ok I found a solution, how I can disable the scrollview in landscape mode. First I define the scrollview in the Page like this:
    private ScrollView scrollView = new ScrollView { Orientation = ScrollOrientation.Vertical };

    Then, I added this to the UpdateLayout Method:

    scrollView.Content = null;
    Content = myLayout;
    

    I also added this to the SetPortraitLayout Method:

    scrollView.Content = myLayout;
    Content = scrollView
    

    How it works? First I clear the content of the scrollview and set the content of the page to the grid (important for landscape). If the portrait layout is set, it should be scrollable. So I add the grid to the scrollview and set the scrollview as page content. This works as expected.

    Maybe it helps somebody.

Answers

  • jezhjezh Member, Xamarin Team Xamurai

    When we check official document Xamarin.Forms ScrollView ,we will find

    Orientation, of type ScrollOrientation, represents the scrolling direction of the ScrollView. The default value of this property is Vertical.

    So,if you don't set property Orientation for ScrollView, it will scroll only in the vertical direction.
    If you want ScrollView scroll in both directions, you can set Orientation to Both,just as follows:

       <ScrollView Orientation="Both">
    
  • WorldOfBastiWorldOfBasti Member ✭✭✭
    edited July 2

    Sorry, I didn't explained my problem well. I try to explain it better:
    My problem is, that it should be scrollable in portrait mode, but not in landscape mode. It looks perfect without a scrollview, but I can't scroll in portrait mode. When I add the scrollview, its perfect in portrait mode but in landscape the height of the boxes are higher and I can scroll, which should not be possible. How can I only use the scrollview in portrait mode?

    As well I tried to set the orientation in portrait to vertical and in landscape to neither, but no success.

  • WorldOfBastiWorldOfBasti Member ✭✭✭
    Accepted Answer

    Ok I found a solution, how I can disable the scrollview in landscape mode. First I define the scrollview in the Page like this:
    private ScrollView scrollView = new ScrollView { Orientation = ScrollOrientation.Vertical };

    Then, I added this to the UpdateLayout Method:

    scrollView.Content = null;
    Content = myLayout;
    

    I also added this to the SetPortraitLayout Method:

    scrollView.Content = myLayout;
    Content = scrollView
    

    How it works? First I clear the content of the scrollview and set the content of the page to the grid (important for landscape). If the portrait layout is set, it should be scrollable. So I add the grid to the scrollview and set the scrollview as page content. This works as expected.

    Maybe it helps somebody.

  • WorldOfBastiWorldOfBasti Member ✭✭✭

    @WorldOfBasti said:
    Ok I found a solution, how I can disable the scrollview in landscape mode. First I define the scrollview in the Page like this:
    private ScrollView scrollView = new ScrollView { Orientation = ScrollOrientation.Vertical };

    Then, I added this to the UpdateLayout Method:

    scrollView.Content = null;
    Content = myLayout;
    

    I also added this to the SetPortraitLayout Method:

    scrollView.Content = myLayout;
    Content = scrollView
    

    How it works? First I clear the content of the scrollview and set the content of the page to the grid (important for landscape). If the portrait layout is set, it should be scrollable. So I add the grid to the scrollview and set the scrollview as page content. This works as expected.

    Maybe it helps somebody.

    Ok I found a problem with my solution. If I use this, it works perfectly on android. On iOS buttons aren't clickable. I tried it with this custom renderer:

    public class ButtonScrollViewRenderer : ScrollViewRenderer 
    { 
        protected override void OnElementChanged(VisualElementChangedEventArgs e) 
        { 
            base.OnElementChanged(e); DelaysContentTouches = false; 
        } 
    }
    

    but nothing happens.

  • WorldOfBastiWorldOfBasti Member ✭✭✭
    edited July 5

    @WorldOfBasti said:

    @WorldOfBasti said:
    Ok I found a solution, how I can disable the scrollview in landscape mode. First I define the scrollview in the Page like this:
    private ScrollView scrollView = new ScrollView { Orientation = ScrollOrientation.Vertical };

    Then, I added this to the UpdateLayout Method:

    scrollView.Content = null;
    Content = myLayout;
    

    I also added this to the SetPortraitLayout Method:

    scrollView.Content = myLayout;
    Content = scrollView
    

    How it works? First I clear the content of the scrollview and set the content of the page to the grid (important for landscape). If the portrait layout is set, it should be scrollable. So I add the grid to the scrollview and set the scrollview as page content. This works as expected.

    Maybe it helps somebody.

    Ok I found a problem with my solution. If I use this, it works perfectly on android. On iOS buttons aren't clickable. I tried it with this custom renderer:

    public class ButtonScrollViewRenderer : ScrollViewRenderer 
    { 
      protected override void OnElementChanged(VisualElementChangedEventArgs e) 
      { 
          base.OnElementChanged(e); DelaysContentTouches = false; 
      } 
    }
    

    but nothing happens.

    I finally fixed this too. I removed my old solution and set the RowDefinitions of each row like this:

    myLayout.RowDefinitions.Add(new RowDefinition { Height = height / 8 });
    

    So now the height is perfect for each row and scrolling is disabled for landscape. I divided it with eight, because I using eight rows now.

Sign In or Register to comment.