Why do AbsoluteLayout.LayoutBounds work incorrect in Xamarin? - xamarin

I don't understand why is there so much space before the end of the screen(photo attached, platform - Android).
It looks like AbsoluteLayout fills not all the space of the screen, but it's not true.Where are also spaces between 'White' buttons(one button should take 20% of the screen; first starts after 4% from the left edge of the screen, second - after 28%: 28% - 4% -20% = 4% free space between buttons)????
Here is xaml code:
<?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="PokerCalculator.OutsCalculator"
BackgroundColor="#131313">
<AbsoluteLayout BackgroundColor="HotPink">
<Label Text="Number of outs:"
FontSize="Medium"
AbsoluteLayout.LayoutBounds="0.04,0,0.3,0.18"
AbsoluteLayout.LayoutFlags="SizeProportional, PositionProportional"
BackgroundColor="Aqua"/>
<Label x:Name="lblOutNumber"
Text="15"
AbsoluteLayout.LayoutBounds="0.35,0,0.18,0.18"
AbsoluteLayout.LayoutFlags="SizeProportional, PositionProportional"
BackgroundColor="Azure"/>
<Button x:Name="btnBack"
Text="BACK"
Clicked="btnBack_Clicked"
AbsoluteLayout.LayoutBounds="0.7,0,0.28,0.18"
AbsoluteLayout.LayoutFlags="SizeProportional, PositionProportional"
BackgroundColor="Fuchsia"/>
<Button BackgroundColor="White"
AbsoluteLayout.LayoutBounds="0.04,0.2,0.20,0.28"
AbsoluteLayout.LayoutFlags="All"/>
<Button BackgroundColor="White"
AbsoluteLayout.LayoutBounds="0.28,0.2,0.20,0.28"
AbsoluteLayout.LayoutFlags="All"/>
<Button BackgroundColor="White"
AbsoluteLayout.LayoutBounds="0.52,0.2,0.20,0.28"
AbsoluteLayout.LayoutFlags="All"/>
<Button BackgroundColor="White"
AbsoluteLayout.LayoutBounds="0.76,0.2,0.20,0.28"
AbsoluteLayout.LayoutFlags="All"/>
</AbsoluteLayout>
</ContentPage>
photo
Photo(mockup)

As discussed on here forum
Absolute layout proportional does not work/calculated as what you expect. Your intention can be achieved using the relativelayout instead.
Lets say that you set X = 0.5 and Width = 0.5.
With your intention you might be expecting the element's X to start from the center and filling the second right half of the absolutelayout bound? No.
The answer is that the element will be 50% width of the layout bound and be right in the center. Making the X position such as (0.5 * absolutelayoutWidth) - (0.5 * elementWidth) (formula is something like this i guess?)
I suggest using relativelayout

As a late answer, I've put a nuget package with a fork of AbsoluteLayout but working in a more predictable way.
Install nuget package SmartMachines.AbsoluteLayout, add namespace xmlns:sm="clr-namespace:SmartMachines;assembly=AbsoluteLayout" and you will have exactly same AbsoluteLayout as native Xamarin, but with expected Proportional alignment behavior.
Hope that will save other people several hours on googling and debugging.

Related

Moving a list of items vertically

I have a map and a list of items underneath.
I want to move the list up (while maintaining the position of the map) until the user reaches the last element of the list. In that case, the list shouldn't move up anymore.
The problem is that the list continues to move upwards even after the last element has been shown living a white background.
template:
<GridLayout rows="*, *, 0" columns="*">
<MapView row="0" col="0"> ...
<GridLayout #list rows="*, 0" columns="*" #list row="1" col="0">
<GridLayout row="0" col="0" class="m-15"
rows="..." (pan)="onPan($event)">
...
</GridLayout>
</GridLayout>
<GridLayout #ref row="2" col="0">...
component.ts
onPan(args: PanGestureEventData) {
switch (args.state) {
case 1:
break;
case 2:
const diff = this.ref.nativeElement.getLocationRelativeTo(this.list.nativeElement);
if (diff > 1400) return; // I used 1400 seems based on various devices sizes, it seems like a good number.
this.dragContainer.translateY += args.deltaY - this.prevDeltaY;
this.prevDeltaY = args.deltaY;
break;
case 3:
default:
break;
}
}
**Expected: **
- I expect that when the last element in the list has been shown, the list is not able to move up anymore
**Actual: **
- The list continues to move upward leaving a white background.
I have created a demo on nativescript playground here https://play.nativescript.org/?template=play-ng&id=rB4H2M
I finally was able to find an example which basically does what I needed. The effect I was trying to achieve is called Parallax and here is an example of Nativescript Demo Samples
https://play.nativescript.org/?template=play-ng&id=b9hyJh&v=2

Xamarin Forms: AbsoluteLayout

I need to use an AbsoluteLayout for other controls on the page not listed here. How do I layout a common senerio where I have a SearchBar at the top, then a ListView which fills the rest of the screen.
I tried this, but the ListView goes incorrectly under the SearchBar
<AbsoluteLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<SearchBar></SearchBar>
<ListView
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,1,1">
</ListView>
</AbsoluteLayout>
Part of the problem is AbsoluteLayoutFlags you have set on the listview.
when you set it to all, you are telling the layout to start at 0,0 and go all the way to 1,1. Which is why the listview is appearing on the searchbar.
<AbsoluteLayout VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<SearchBar AbsoluteLayout.LayoutBounds="0,0,1,40"
AbsoluteLayout.LayoutFlags="WidthProportional,PositionProportional"/>
<ListView
AbsoluteLayout.LayoutFlags="XProportional,SizeProportional"
AbsoluteLayout.LayoutBounds="0,40,1,1">
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>mono</x:String>
<x:String>monodroid</x:String>
<x:String>monotouch</x:String>
<x:String>monorail</x:String>
<x:String>monodevelop</x:String>
<x:String>monotone</x:String>
<x:String>monopoly</x:String>
<x:String>monomodal</x:String>
<x:String>mononucleosis</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</AbsoluteLayout>
Xamarin Documentation
I am sure you were referencing the documentation. I linked it here and quoting part of it. Hopefully it helps.
Proportional values define a relationship between a layout and a view.
This relationship defines a child view's position or scale value as a
proportion of the corresponding value of the parent layout. These
values are expressed as doubles with values between 0 and 1.
Proportional values are used to position and size views within the
layout. So, when a view's width is set as a proportion, the resultant
width value is the proportion multiplied by the AbsoluteLayout's
width. For example, with an AbsoluteLayout of width 500 and a view set
to have a proportional width of .5, the rendered width of the view
will be 250 (500 x .5).

What properties it is necessary to set view1, so that it fills the rest of the window?

What properties it is necessary to set view1, so that it fills the rest of the window?
<Alloy>
<Window>
<View id="view1">
</View>
<View id="view2" height="50">
</View>
</Window>
</Alloy>
<Alloy>
<Window>
<View id="view1" top="0" bottom="50" width="100%">
</View>
<View id="view2" height="50" bottom="0" width="100%">
</View>
</Window>
</Alloy>
Also it is good to put the dimensions in the style (TSS) file instead of putting them in the view XML file. If this resolves your query then mark it as an answer for the reference for the rest of the community.
There are multiple ways to fill dimensions. It depends on what kind of layout type you have used like - vertical, horizontal or composite (default).
Vertical
Aligns children below each other.
You can control width, left, right, top & bottom properties. (bottom property doesn't work for last child)
Last child can occupy rest of the vertical height of parent.
Horizontal:
Aligns children from left-to-right in horizontal plane.
Can control left, right, top & bottom properties (right property doesn't work for last child).
Last child can occupy remaining width of view
Composite or default
Most flexible if you have not oriented UI.
Can keep views anywhere using top,left,right,bottom.
Assigning left & right only will define the width. Adding width with left & right will obey width keeping left & right restrictions.
-- e.g. if left & right = 20 & width=Ti.UI.SIZE, then view will start from left & will have width as Ti.UI.SIZE & will not go beyond right=20
Same rule as above applies for height as well.

NativeScript StackLayout let a child element take remaining width

In the NativeScript StackLayout, I have three elements A, B and C. I want the middle element B to take up all the available space. This is what i want:
|ABBBBBBBBBBBBC|
I'm trying with this simplified code. A and C are labels with a fixed width, B is a progress bar.
<StackLayout orientation="horizontal" verticalAlignment="center">
<Label text="1" width="50"></Label>
<Progress value="50" maxValue="100"></Progress>
<Label text="1" width="50"></Label>
</StackLayout>
What happens is that the progress bar fills up the remaining space of the StackLayout, leaving no space for the last label. Only the first label and the Progress bar itself are drawn on the screen, like this:
|ABBBBBBBBBBBBB|C
So the C elements is drawn beyond the screen.
If I place the 2 labels in front, sizing looks ok.
What am I doing wrong here?
Use a GridLayout.
<GridLayout columns="50, *, 50">
<Label text="1" col="0"></Label>
<Progress value="50" maxValue="100" col="1"></Progress>
<Label text="1" col="2"></Label>
</GridLayout>

Coordinates of children of canvas element

There are a few rectangles inside a canvas. How can I get the coordinates of the rectangles wrt canvas using the Name of rectangles in C# ?
You can do this using TransformToVisual. There's a good example here: Visual.TransformToVisual MSDN
From the page for Posterity:
<StackPanel Name="myStackPanel" Margin="8">
<TextBlock Name="myTextBlock" Margin="4" Text="Hello, world" />
</StackPanel>
// Return the general transform for the specified visual object.
GeneralTransform generalTransform1 = myStackPanel.TransformToVisual(myTextBlock);
// Retrieve the point value relative to the child.
Point currentPoint = generalTransform1.Transform(new Point(0, 0));

Resources