How to make an AbsoluteLayout scrollable (or is there another way?)

I have a data entry form that can be quite long and I have some buttons that push over from the right-hand side of the screen and I want them pinned there at the top right-hand corner of the screen so they can save their work without having to scroll up top. Right now I have an AbsoluteLayout that performs that function perfectly, but it does not allow the user to scroll when the form is longer than the screen. I can get it to scroll using a ScrollView within the AbsoluteLayout, but then when the user scrolls, the buttons do not stay put. I have tried StackLayouts within the AbsoluteLayout, and every combination of the 3 views that I can think of but nothing seems to work.

Is there a way to do this?

Tagged:

Best Answer

Answers

  • TobeTobe DEMember ✭✭

    If I understand this right, you can just put the Button in another Layout for the top, set only the Text in the Scrollview, and then create a StackLayout with your Button and your ScrollView.

    I'm not quite sure what you mean with "data entry form", I used an editor for this example. Note that tapping into the editor to edit text will push the keyboard to top and maybe scroll the editor too much / too less. There are workarounds for this, you have to google them if you want to use the Editor class or any other class where the user can enter text. Xamarin has a lot of problems with multiple scrolling like keyboard scrolling and editor scrolling.

    Example:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using Xamarin.Forms;
    
    namespace MyNameSpace
    {
        class MyPage : ContentPage
        {
    
            public MyPage()
            {
                var button = new Button
                {
                    Text = "Save",
                    HorizontalOptions = LayoutOptions.End,
                    VerticalOptions = LayoutOptions.Start
                };
    
                var editor = new Editor
                {
                    Text = @"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 
                    At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, 
                    consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
                    Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
                    Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 
                    At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, 
                    consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
                    Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
                    Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 
                    At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, 
                    consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
                    Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
                    Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 
                    At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, 
                    consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
                    Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
                    HorizontalOptions = LayoutOptions.FillAndExpand,
                    VerticalOptions = LayoutOptions.Start
                };
    
                var scrollView = new ScrollView
                {
                    Content = editor
                };
    
                var layout = new StackLayout
                {
                    Children = {button, scrollView},
                    Orientation = StackOrientation.Vertical
                };
    
                Content = layout;
            }
        }
    }
    
  • BobHowardBobHoward USMember ✭✭
    edited December 2016

    That works for keeping them at the top in their own section, but I need the buttons to overlap the content and stay at the edge of the screen like this..

  • BobHowardBobHoward USMember ✭✭

    That worked! Not sure I understand it yet though :smile:

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    I would suggest an alternative approach, which is instead of bunches of nested stack layouts, you need a Grid.

    This layout is begging you to be a grid. Please, please use a grid.

    If you do not know how to use a grid, I can go find the samples quick, but Xamarin has some good ones you can easily find.

    Ending layout will be Abs Layout wraps buttons and ScrollView which wraps the grid.

  • TobeTobe DEMember ✭✭

    In the example we put everything that should be scrollable into a StackLayout (can be any other layout I guess, but imo StackLayout is the easiest), and put only that StackLayout into the ScrollView.
    Think about it like this: the ScrollView puts an invisible frame around the StackLayout, everything inside this frame is scrollable.

    The AbsoluteLayout is the Content of the whole page, so it fills the whole screen. First we add the ScrollView with a Rectangle (1,1,1,1), so the ScrollView fills the AbsoluteLayout (and by that the whole screen) to 100% in all directions.
    After that we add the two buttons to the AbsoluteLayout. The cool thing about AbsolutLayout and RelativeLayout is, that elements can overlap. By adding the buttons AFTER the scrollview, they are "on top of" the ScrollView.
    Because the buttons are not inside the layout that is inside the ScrollView, the buttons are not scrollable, but stay where they are told to by the AbsoluteLayout.

    @AdamMeaney You are right, the content of the StackLayout (the picture, all the labels and entries) can also be inserted into a grid, that would make the code probably a bit nicer. But for this example it doesn't really matter, all that matters is the endresult: add ScrollView to AbsoluteLayout, then the Buttons. How you make up the content of the ScrollView doesn't really matter.

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    The performance of nested stacklayouts is awful if you have too many of them. Scrolling like that with nested StackLayouts gets extremely laggy sometimes, especially if it is ever decided to add more to the nested things, like images or anything else.

    Changing to a grid is not NECESSARY, but is definitely the right call.

  • TobeTobe DEMember ✭✭

    Didn't know about the performance issues, thanks :smiley: When I started our app I was new to all this and only used StackLayouts, so although this example was created in a rush and is not meant to be pretty, it kinda shows how I build our layouts.
    Looks like I have to read that grid guide and start experimenting with it after all, I was too lazy up too now :blush:
    But thats something for the new year :wink:

  • BobHowardBobHoward USMember ✭✭

    I do have the buttons inside a grid which is why they are stacked but I don't think a grid would work because I want the content to scroll but not the buttons.

  • AdamMeaneyAdamMeaney USMember ✭✭✭✭✭

    @BobHoward The grid replaces the stacks in the accepted answer. Not the other layouts.

  • BobHowardBobHoward USMember ✭✭

    Interestingly, even though I am adding the buttons last to the AbsoluteLayout, they visually are behind the other controls, I have to call RaiseChild on the layout to get them to the front.

  • TobeTobe DEMember ✭✭

    @BobHoward How many AbsoluteLayouts do you have in the ContentPage? It should only be one at the very top of the hierarchy (i.e. as the content of the ContentPage).
    Maybe you can show us some code?

  • BobHowardBobHoward USMember ✭✭

    Yes, just one, and on my grid that contains my buttons, I set these

    AbsoluteLayout.SetLayoutFlags(this, AbsoluteLayoutFlags.PositionProportional);
    Rectangle oRec = new Rectangle(0.95f, 0.05f, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize);
    AbsoluteLayout.SetLayoutBounds(this, oRec);

    and on my content, I set these:

    var stackLayout = new StackLayout { Children = { ContentGrid} };
    var scrollView = new ScrollView { Content = stackLayout };

    AbsoluteLayout.SetLayoutBounds(scrollView, new Rectangle(1, 1, 1, 1));
    AbsoluteLayout.SetLayoutFlags(scrollView, AbsoluteLayoutFlags.All);

Sign In or Register to comment.