AbsoluteLayout not working as expected

threadythready CAMember ✭✭✭
edited July 2016 in Xamarin.Forms

Hi Folks,

I have some very weird placement of controls with absoluteLayout. The whole thing looks buggy to me actually. Instead of giving an example from my own code, please see this page: https://adventuresinxamarinforms.com/2015/05/05/demystifying-xamarin-forms-absolutelayout-and-relativelayout-positioning/

From that page, it's this portion that perfectly explains my question:

Oh dear! That’s not what I expected. The BoxView is offset so that it falls short of the correct x and y positions. Why has this happened? It took me a while to wrap my head around this but essentially the AbsoluteLayout also takes into account the size of the control when calculating the relative x and y position. In other words it is 25% of the AbsoluteLayout less the size of the control. Why would it do this? That’s a good question.>

It boils down to this. The box generated from these 2 separate ways of placing color on a form should be in the exact same position but they are not:

The red box is correct:
<Grid RowSpacing="0" ColumnSpacing="0"> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="*" /> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <BoxView Grid.Row="1" Grid.Column="1" BackgroundColor="Red" /> </Grid>

This yellow box is not correct:
<AbsoluteLayout Opacity="0.75"> <BoxView Color="Yellow" AbsoluteLayout.LayoutBounds="0.25,0.25,0.25,0.25" AbsoluteLayout.LayoutFlags="All" /> </AbsoluteLayout>
I think there must be a bug with AbsoluteLayout. Does anyone agree?

Thanks for your help.

Mike

Answers

  • threadythready CAMember ✭✭✭

    For instance, here's a simple example anyone can paste in. It seems clear to me that there are two boxes here which are at the top of the screen on the same row - each taking 50% of the screen for their column width and 10% of height of screen for height.

    As you can see from the pic - the width seems messed up. Or am I just not getting it?

    <?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="absoluteLayout.absoluteLayoutProblemHere"> <AbsoluteLayout Opacity="0.75" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" > <BoxView Color="Red" AbsoluteLayout.LayoutBounds="0.25, 0.05, 0.5, 0.1" AbsoluteLayout.LayoutFlags="All" /> <BoxView Color="Green" AbsoluteLayout.LayoutBounds="0.75, 0.05, 0.5, 0.1" AbsoluteLayout.LayoutFlags="All" /> </AbsoluteLayout> </ContentPage>

    Thanks,
    Mike

  • AdamPAdamP AUUniversity ✭✭✭✭✭

    Hi @thready - 0.5 as your width is 0.5 of the entire screen size but you have offset it by 0.25. So the width is correct but because of the offset they are both bigger than you expect.

    Hence if you did this would would get 2 equal size boxes next to each other.

     <AbsoluteLayout Opacity="0.75"
          VerticalOptions="FillAndExpand"
          HorizontalOptions="FillAndExpand"
          >
          <BoxView Color="Red"
            AbsoluteLayout.LayoutBounds="0.25, 0.05, 0.25, 0.1"
            AbsoluteLayout.LayoutFlags="All"
            />
          <BoxView Color="Green"
            AbsoluteLayout.LayoutBounds="0.75, 0.05, 0.25, 0.1"
            AbsoluteLayout.LayoutFlags="All"
            />
        </AbsoluteLayout>
    

    Hopefully that makes sense.

  • threadythready CAMember ✭✭✭

    Thanks Adam!

    ok that works as I'd expect it. But I still don't get why mine doesn't work. The one you did produces 2 equal sized boxes of width = 25% of layout.

    I chose a width for each control of 50%, centered at 25 and 75 percent of width- which in my mind should have taken up all the horizontal space of the layout (leaving no empty space - with each control taking exactly 50% of the space)...

    How would I do that?

  • samymesbahsamymesbah Member

    I know this is an old thread but I was having exactly the same problem today. It looks like Xamarin subtracts from the right or bottom if X or Y is past the halfway point - so for your example:

    0.75, 0.05, 0.5, 0.1

    would change to

    1, 0.05, 0.5, 0.1

    which positions the block from .5 to 1 and if you center in there it works,

  • smartmachinessmartmachines Member ✭✭

    I've put a nuget package with a fork of AbsoluteLayout but working as we expect.

    Install nuget package SmartMachines.AbsoluteLayout, add namespace xmlns:sm="clr-namespace:SmartMachines;assembly=AbsoluteLayout" and enjoy <sm:AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></sm:AbsoluteLayout>.

    Hope that will save other people several hours on googling and debugging (feel free to help bugfix on github).

  • thedeethedee USMember ✭✭

    @smartmachines said:
    I've put a nuget package with a fork of AbsoluteLayout but working as we expect.

    Install nuget package SmartMachines.AbsoluteLayout, add namespace xmlns:sm="clr-namespace:SmartMachines;assembly=AbsoluteLayout" and enjoy <sm:AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></sm:AbsoluteLayout>.

    Hope that will save other people several hours on googling and debugging (feel free to help bugfix on github).

    Do you know how to set the AbsoluteLayout.SetLayoutBounds so that it is positioned based off of the location of another control? Essentially I have a grid that can have many rows with a entry control. If the user clicks on the entry control I want to show my little popup by the control they clicked.

  • smartmachinessmartmachines Member ✭✭

    @DerekHagen said:

    @smartmachines said:
    I've put a nuget package with a fork of AbsoluteLayout but working as we expect.

    Install nuget package SmartMachines.AbsoluteLayout, add namespace xmlns:sm="clr-namespace:SmartMachines;assembly=AbsoluteLayout" and enjoy <sm:AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"></sm:AbsoluteLayout>.

    Hope that will save other people several hours on googling and debugging (feel free to help bugfix on github).

    Do you know how to set the AbsoluteLayout.SetLayoutBounds so that it is positioned based off of the location of another control? Essentially I have a grid that can have many rows with a entry control. If the user clicks on the entry control I want to show my little popup by the control they clicked.

    I think you can not do it directly, but something like that might work:

        void OnClicked(object sender, EventArgs args)
        {
            var senderElement = sender as VisualElement;
    
            var targetRect = new Rectangle(senderElement.X, senderElement.Y, senderElement.Width, senderElement.Height);
    
            const int numberOfParentViews = 1;
            var parent = senderElement.Parent as VisualElement;
            for (int i = 0; i < numberOfParentViews; i++)
            {
                targetRect.X += parent.X;
                targetRect.Y += parent.Y;
                parent = senderElement.Parent as VisualElement;
            }
    
            AbsoluteLayout.SetLayoutBounds(tooltip, targetRect);
        }
    

    Where OnClicked is a method that is called when you click the entry control,
    tooltip is a variable for your popup.

    You will also need to note how many parent views do you have between the entry control and the tooltip (if it is within the same layout, put numberofParentViews =0).

Sign In or Register to comment.