Absolute Layout inside Stack Layout - xamarin.forms

I'm trying to add a floating button in the bottom right corner of my page inside the StackLayout
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:fab="clr-namespace:FAB.Forms;assembly=FAB.Forms"
x:Class="Hura.Pages.LatestNews"
Title="Latest news">
<StackLayout Spacing="10" Padding="5">
<Label Text="Latest news" FontSize="Medium"/>
<ListView x:Name="lsvNews"/>
<Label Text="Latest activities" FontSize="Medium"/>
<ListView x:Name="lsvActivities"/>
<Label Text="Good Mording" FontSize="Large" HorizontalOptions="Center"/>
<AbsoluteLayout x:Name="xyz"
BackgroundColor="Transparent"
HorizontalOptions="End"
VerticalOptions="End">
<Button Text="gggggg"/>
</AbsoluteLayout>
</StackLayout>
</ContentPage>
but the button appears bellow the label. But I want it to appear above the label and not below it.
How can I position the button in the bottom-left corner above the label?

Your issue here is that the StackLayout is simply going to position items in the order that you add them. So since you added the AbsoluteLayout after adding your Label, your Button is going to show up lower than your Label.
Obviously you could move the Label beneath your AbsoluteLayout and get the effect you are asking for like so:
...
<AbsoluteLayout x:Name="xyz"
BackgroundColor="Transparent"
HorizontalOptions="End"
VerticalOptions="End">
<Button Text="gggggg"/>
</AbsoluteLayout>
<Label Text="Good Mording" FontSize="Large" HorizontalOptions="Center"/>
...
But the whole point of a floating button is for it to actually float above other content. In the example that you show, your Button would never float above anything. In order to get the Button to float over other items you would need to add the entire StackLayout to your AbsoluteLayout. Something like this (note that I have not tested this code so you may need to play with it a bit):
<AbsoluteLayout VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand">
<StackLayout Spacing="10"
Padding="5"
AbsoluteLayout.LayoutFlags="All"
AbsoluteLayout.LayoutBounds="0,0,1,1">
...
</StackLayout>
<Button Text="gggggg"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds="1,1,AutoSize,AutoSize"/>
</AbsoluteLayout>
The important bits above are that everything is within the AbsoluteLayout, which means you are able to stack your controls correctly. The other important items are the AbsoluteLayout.LayoutFlags and AbsoluteLayout.LayoutBounds. The LayoutFlags and LayoutBounds on the StackLayout basically just tell the StackLayout that it can take up the entire screen. The LayoutFlags and LayoutBounds on the Button say that the Button needs to be in the bottom right corner and that it can size itself.

Make it reverse put Stack Layout inside Absolute Layout to work like expected
Here is sample code
Button btnPlus = new Button()
{
Text = "FAB"
HeightRequest = 50,
WidthRequest = 50
};
StackLayout stackLayout = new StackLayout
{
Children = { STACK_CHILDRENS }
};
AbsoluteLayout absoluteLayout = new AbsoluteLayout();
AbsoluteLayout.SetLayoutFlags(btnPlus, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(btnPlus, new Rectangle(0.5, 0.95, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
AbsoluteLayout.SetLayoutFlags(stackLayout, AbsoluteLayoutFlags.All);
AbsoluteLayout.SetLayoutBounds(stackLayout, new Rectangle(0f, 0f, 1f, 1f));
absoluteLayout.Children.Add(btnPlus);
absoluteLayout.Children.Add(stackLayout);
Content = absoluteLayout;

Related

Xamarin Froms and SkiaSharp, Hightlight an Area on Image

I use the below code to show image on a from.
<ContentPage>
<ContentPage.Content>
<Grid>
// Row definitions here
// Column definitions here
<Image
Grid.Column="0"
Grid.Row="0"
x:Name="myStoryPage"
Grid.ColumnSpan="3">
</Image>
<!-- Next, previous buttons here -->
<skiaforms:SKCanvasView x:Name="canvasView"
PaintSurface="canvasView_PaintSurface"
Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="3"
AbsoluteLayout.LayoutBounds="10, 0, 5, 65"/>
</Grid>
</ContentPage.Content>
</ContentPage>
Now I need to highlight an area in the image using SkiaSharp.
I could do drawing a line under the grid using the SKCanvasView. But I want to draw over the image.
I thought to use use AbsoluteLayout but as my page is a ContentPage, I could not use the AbsoluteLayout outside of the content.
If I could use AbsoluteLayout, I can dynamically position it using C# in code behind.

How to wrap content of visible elements only in xamarin forms control

I have a control in Xamarin Forms where I have a bunch of labels that are visible or invisible based on a few factors.
I want the layout I'm calling the control from to wrap the height based on the labels that are visible. So if the labels are 100dp tall for example (I don't actually know how tall they are) and there are 3 visible, I want the height of the control/layout to be 300dp. Right now the layout is just stretching out to what it would look like if all the labels were visible.
This is my control:
<controls:cardDetail>
<Label Text="hi1" IsVisible="{Binding maybe1}">
<Label Text="hi2" IsVisible="{Binding maybe2}">
<Label Text="hi3" IsVisible="{Binding maybe3}">
<Label Text="hi4" IsVisible="{Binding maybe4}">
<Label Text="hi5" IsVisible="{Binding maybe5}">
<Label Text="hi6" IsVisible="{Binding maybe6}">
</controls:cardDetail>
I call this control from a carousel view inside a stacklayout in another xaml page:
<StackLayout orientation="Horizontal">
<CarouselView x:Name="carView">
<controls:cardDetail/>
</CarouselView>
</StackLayout>
What do I have to do to which page/layout to make this happen? Do I need to use C# or can I just add an attribute in xaml??
Thanks!

Xamarin Forms Transalted Button click

I am creating a rounded menu with Xamarin Forms as Below.
The accent color is my Grid. Then I translatex and trnaslatey the buttons.
My issue is that the click button is not raised. I have also tried on the gesture recognizer of my stack panel. Same result.
The part of the code is below:
<Grid BackgroundColor="Accent" Margin="0,0,0,10" VerticalOptions="End" HorizontalOptions="Center">
<StackLayout x:Name="cat" TranslationX="-109" TranslationY="-102"
>
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="catBtn_Clicked"/>
</StackLayout.GestureRecognizers>
<Button Clicked="catBtn_Clicked" WidthRequest="60"
HeightRequest="60"
FontSize="35"
CornerRadius="30" HorizontalOptions="Center"
BackgroundColor="{StaticResource RedColor}"
TextColor="White"
Text="{ x:Static local:GrialIconsFont.Calendar }"
FontFamily="{ StaticResource IconsFontFamily }">
</Button>
<Label Text="{extensions:Translate Hello}" HorizontalOptions="Center"/>
</StackLayout>
Make sure that your button is placed inside superView's bounds,
If a button is placed outside superView's bounds, the button will not clickable.
You use TranslationX="-109" and TranslationY="-102" will make the button out of the bounds of StackLayout, so it won't response to the click event. You can add backgroundColor to stacklayout to see its bounds.
I would suggest you to add those buttons or labels directly to Grid and use absolute-layout, relative-layout or other layout to fix their positions.
There are also some examples in Github you can refer, such as CircleButtonMenu, Xamarin.Forms-RadialMenu

How to move scroll programmatically to Scroll View, when the text no longer fits on the screen?

good day, I'm having a problem with a scroll view, I have a label in a horizontal scroll view, that label concateno amounts, the problem is when the text no longer fit on the screen, the scroll does not move, and I would like if I enter a new quantity in the label, the scroll scrolls so that the last added quantity can be visible, I hope you can help me
This is my XAML:
<ScrollView x:Name="SV" Orientation="Horizontal" HorizontalScrollBarVisibility="Never" HorizontalOptions="FillAndExpand">
<Label Text="{Binding FullSumList}" TextColor="#000000" FontSize="{extensions:ScalableFont 30}" VerticalOptions="EndAndExpand" HorizontalOptions="EndAndExpand" />
</ScrollView>
I searched, not to find a solution
there if I write a quantity, should the scroll go to the left, so that the new quantity is seen
You can use the ScrollToAsync method.
In your xaml
<ScrollView x:Name="SV" Orientation="Horizontal" HorizontalScrollBarVisibility="Never" HorizontalOptions="FillAndExpand">
<Label x:Name="labelTest" Text="{Binding FullSumList}" TextColor="#000000" FontSize="{extensions:ScalableFont 30}" VerticalOptions="EndAndExpand" HorizontalOptions="EndAndExpand" />
</ScrollView>
In the code-behind
SV.ScrollToAsync(labelTest, ScrollToPosition.End, true);

How can I make an image auto-resize so the width is 100% and the height adjusted accordingly?

I have the following simple XAML page:
<?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="Test.UserGuides.VPN">
<ContentPage.Content>
<ScrollView>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center" Margin="10,10,10,10">
<Label Margin="10,10,10,10" Text="How to connect to VPN." HorizontalOptions="Center" />
<Label Margin="10,10,10,10" Text="If you have a corporate notebook, look for the Cisco AnyConnect application. Either in your start menu, on your desktop, or in your taskbar." />
<Image x:Name="imgVPN1" Margin="10,10,10,10" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
<Label Margin="10,10,10,10" Text="Select your region and press the Connect button." />
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
In the constructor, I call a method to load the images:
private void LoadImages()
{
imgVPN1.Aspect = Aspect.AspectFit;
ImageSource imagesrc = ImageSource.FromResource("Test.Files.CiscoAnyConnect.PNG");
imgVPN1.Source = imagesrc;
}
The result looks like this on my (rather large, high DPI) phone:
imgur link 1
Of course, I want the image to automatically expand so it takes up the entire width of the screen. While maintaining the aspect ratio. But how can I achieve this? I've already tried putting the Aspect to "AspectFill", and added
imgVPN1.WidthRequest = Application.Current.MainPage.Width;
To the LoadImages method, but that makes the end result look like this:
imgur link 2
I've been toying around with various HorizontalOptions, VerticalOptions, Aspects, GridView, StackLayouts,... The end result is always either the first or the second screenshot. So how can I achieve what I want here?
Here is what can be done. XML almost didn't change, I just removed image Layout Options
<ContentPage.Content>
<ScrollView>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center" Margin="10,10,10,10">
<Label Margin="10,10,10,10" Text="How to connect to VPN." HorizontalOptions="Center" />
<Label Margin="10,10,10,10" Text="If you have a corporate notebook, look for the Cisco AnyConnect application. Either in your start menu, on your desktop, or in your taskbar." />
<Image x:Name="imgVPN1" Margin="10,10,10,10" />
<Label Margin="10,10,10,10" Text="Select your region and press the Connect button." />
</StackLayout>
</ScrollView>
</ContentPage.Content>
After implementing everything in relative layout which also was not simple (I have the code if anybody needs it let me know) I found easier way. The key point is that image doesn't scale correctly and occupies too much space in height. But we know the size ratio of this image so we can use it. In the code we need to override OnSizeAllocated because in constructor the width is unknown yet. Then it's easy
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
imgVPN1.WidthRequest = width;
imgVPN1.HeightRequest = width / 2.152; //given that image is 411 x 191
}
You could use other width than page with if you want. For example you could use stack layout width to consider margins for more accuracy but this is already tuning. Or you actually could use the image width itself like that
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
double needHeight=imgVPN1.Width / 2.152;
if (imgVPN1.Height != needHeight)
imgVPN1.HeightRequest = needHeight;
}
Here is what you need.
<ContentPage.Content>
<ScrollView>
<StackLayout Margin="20" Spacing="10">
<Label Text="How to connect to VPN." HorizontalOptions="Center" />
<Label Text="If you have a corporate notebook, look for the Cisco AnyConnect application. Either in your start menu, on your desktop, or in your taskbar." />
<Image Source="yourimage.jpg" HorizontalOptions="Fill" />
<Label Text="Select your region and press the Connect button." />
</StackLayout>
</ScrollView>
</ContentPage.Content>

Resources