I am trying to create a dynamic chessboard based on user input(The user inputs 10x 8y and it establishes a 10x8 board). I can't seem to keep the grid inside its own area and fill the full area provided. I was wondering how I would fix this issue
xaml code
<StackLayout >
<StackLayout x:Name="User_Input" BackgroundColor="Green">
<Label Text="Enter Length of Grid" TextColor="Black" FontSize="Body"/>
<Entry x:Name="xEntry" Placeholder="0" />
<Label Text="Enter Width of Grid" TextColor="Black" FontSize="Body"/>
<Entry x:Name="yEntry" Placeholder="0" />
<Button x:Name="btnStart" Clicked="btnStart_Clicked" Text="Start"/>
</StackLayout>
<Frame x:Name="Game" BorderColor="Black">
<Grid x:Name="Game_Grid" BackgroundColor="RoyalBlue" Margin="0" HeightRequest="400" WidthRequest="100">
</Grid>
</Frame>
</StackLayout>
C# Code
private void btnStart_Clicked(object sender, EventArgs e)
{
//User_Input.IsVisible = false;
//Game.IsVisible = true;
int max_x = Int32.Parse(xEntry.Text);
int max_y = Int32.Parse(yEntry.Text);
cellGrid main = new cellGrid(max_x,max_y);
for (int y = 0; y < max_y; y++)
{
ColumnDefinition c = new ColumnDefinition();
c.Width = new GridLength(1, GridUnitType.Auto);
Game_Grid.ColumnDefinitions.Add(c);
for(int x = 0; x < max_x; x++)
{
RowDefinition r = new RowDefinition();
r.Height = new GridLength(1, GridUnitType.Auto);
Game_Grid.RowDefinitions.Add(r);
Label cell = new Label {
HorizontalOptions = LayoutOptions.Fill
,VerticalOptions = LayoutOptions.Fill,
WidthRequest = Game_Grid.WidthRequest / max_x,
HeightRequest = Game_Grid.HeightRequest / max_y,
};
cell.Background = new SolidColorBrush(Color.Black);
Game_Grid.Children.Add(cell, x,y);
}
}
}
Image of the Output
Related
I am trying to build a Revit plugin using WPF and I am trying to add controls to a window dynamically. However, these controls are not getting displayed in the window and there is no error. Any help would be appreciated. Thank you.
Xaml
<ScrollViewer Margin="0,190,-0.4,-1">
<StackPanel Name="TaskList" Height="auto" Width="auto">
</StackPanel>
</ScrollViewer>
c#
for (var i = 0; i < dt.Rows.Count; i++)
{
Canvas canvas = new Canvas();
canvas.Height = 100;
canvas.Width = 300;
canvas.Background = new SolidColorBrush(Colors.Black);
canvas.Margin = new Thickness(20);
System.Windows.Controls.TextBox tb = new System.Windows.Controls.TextBox();
tb.Background = new SolidColorBrush(Colors.Black);
tb.Foreground = new SolidColorBrush(Colors.White);
tb.Width = 300;
tb.FontSize = 30;
tb.Height = 100;
tb.TextWrapping = TextWrapping.Wrap;
tb.MaxLength = 40;
tb.Text = dt.Rows[i][2].ToString();
canvas.Children.Add(tb);
TaskList.Children.Add(canvas);
TaskList.UpdateLayout();
}
EDIT
I am using a page tag as the base not window. Maybe that changes how i should approach the problem?
Remove Canvas entirely. You can add the TextBox elements to the StackPanel (TaskList) directly. If you want a border or spacing then you should use the Border control, not Canvas.
Additionally, only call UpdateLayout() after you've added all the controls to it:
using System.Windows.Controls;
...
for (var i = 0; i < dt.Rows.Count; i++)
{
TextBox tb = new TextBox();
tb.Background = new SolidColorBrush( Colors.Black );
tb.Foreground = new SolidColorBrush( Colors.White );
tb.Width = 300;
tb.FontSize = 30;
tb.Height = 100;
tb.TextWrapping = TextWrapping.Wrap;
tb.MaxLength = 40;
tb.Text = dt.Rows[i][2].ToString();
this.TaskList.Children.Add( tb );
}
this.TaskList.UpdateLayout();
Consider using an ItemsControl, instead of creating UI elements in code behind:
<ScrollViewer>
<ItemsControl x:Name="TaskList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Width="300" Height="100" FontSize="30"
TextWrapping="Wrap" Text="{Binding}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
Then just add strings to its Items property:
for (var i = 0; i < dt.Rows.Count; i++)
{
TaskList.Items.Add(dt.Rows[i][2].ToString());
}
I am dynamically generating a grid and am filling it with content through C# code. The code is as follows:
<?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="WPapp.Views.Home"
x:Name="HomeHeader">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Refresh"
x:Name="refreshButton"
Clicked="refreshButton_Clicked"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<ScrollView>
<StackLayout Margin="10"
HorizontalOptions="Center"
VerticalOptions="FillAndExpand"
x:Name="HomeContainer"
CompressedLayout.IsHeadless="true">
<Label Text="Featured Posts"
FontSize="Title"
FontAttributes="Bold"
Margin="0, 20, 10, 0"/>
<StackLayout x:Name="FeaturedContainer"
CompressedLayout.IsHeadless="true">
</StackLayout>
</StackLayout>
</ScrollView>
</ContentPage.Content>
</ContentPage>
int columnNum = 0;
int rowNum = 0;
foreach (var category in categoryList)
{
Grid postGrid = new Grid();
var column = new ColumnDefinition();
column.Width = new GridLength(5, GridUnitType.Star);
postGrid.ColumnDefinitions.Add(column);
postGrid.ColumnDefinitions.Add(column);
double division = featuredPosts.Count / 2;
double rowCount = Math.Ceiling(division);
for (int i = 0; i < rowCount; i++)
{
var row = new RowDefinition();
row.Height = GridLength.Auto;
postGrid.RowDefinitions.Add(row);
}
foreach (var item in featuredPosts)
{
Frame featuredFrame = new Frame();
featuredFrame.BorderColor = Color.Gray;
featuredFrame.CornerRadius = 5;
featuredFrame.Padding = 20;
Label postTitle = new Label();
postTitle.FontSize = Device.GetNamedSize(NamedSize.Subtitle, typeof(Label));
postTitle.FontAttributes = FontAttributes.Bold;
BoxView titleSeparator = new BoxView();
titleSeparator.Color = Color.Gray;
titleSeparator.HeightRequest = 1;
titleSeparator.HorizontalOptions = LayoutOptions.Fill;
Image postFeaturedImage = new Image();
postFeaturedImage.Aspect = Aspect.AspectFill;
BoxView imageSeparator = new BoxView();
imageSeparator.Color = Color.Gray;
imageSeparator.HeightRequest = 2;
imageSeparator.HorizontalOptions = LayoutOptions.Fill;
Label publishDate = new Label();
publishDate.FontSize = Device.GetNamedSize(NamedSize.Caption, typeof(Label));
StackLayout postDetails = new StackLayout();
postDetails.Children.Add(postTitle);
postDetails.Children.Add(titleSeparator);
postDetails.Children.Add(postFeaturedImage);
postDetails.Children.Add(imageSeparator);
postDetails.Children.Add(publishDate);
featuredFrame.Content = postDetails;
if ((featuredPosts.First() == item) && !(featuredPosts.Count() % 2 == 0))
{
postGrid.Children.Add(featuredFrame, columnNum, rowNum);
Grid.SetColumnSpan(featuredFrame, 2);
columnNum++;
}
else
{
postGrid.Children.Add(featuredFrame, columnNum, rowNum);
Grid.SetColumnSpan(featuredFrame, 1);
}
columnNum++;
if (columnNum == 2)
{
rowNum++;
columnNum = 0;
}
}
FeaturedContainer.Children.Add(postGrid);
columnNum = 0;
rowNum = 0;
}
With this code, this is the result I am getting:
As you can see, the top-left grid height is sized correctly as it is just big enough to fit its children. This is how it should be.
However, the problem is, sometimes the grid cell becomes too big, this is shown in the bottom-left and bottom-right cells. It is too tall! This is only for some of the cells.
What am I doing wrong and how can I fix this so the grid height is just big enough, not too big.
I am using Xamaring form and I would like to transform my Xaml code into c# code.
I have manage to the XAML code but I do know how to do the c# code
here is my code :
<StackLayout Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" x:Name="GridRectangle" >
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="OnImageNewsTappedGridRectangle"/>
</StackLayout.GestureRecognizers>
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Image x:Name="GridRectangleImage" Source="" Aspect="AspectFill" AbsoluteLayout.LayoutBounds="1,1,1,1" AbsoluteLayout.LayoutFlags="All"/>
<AbsoluteLayout AbsoluteLayout.LayoutBounds="1,1,1,1" AbsoluteLayout.LayoutFlags="All" BackgroundColor="#66000000" >
<StackLayout Orientation="Vertical" BackgroundColor="Transparent" AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="1,1,1,1" >
<StackLayout VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand" Padding="3">
<Label x:Name="GridRectangleTitle" Text="" FontSize="Medium" TextColor="White" FontAttributes="Bold"></Label>
</StackLayout>
<StackLayout VerticalOptions="EndAndExpand" HorizontalOptions="EndAndExpand" Padding="3">
<Label x:Name="GridRectangleProviderAndDate" Text="" TextColor="White" FontSize="Small" FontAttributes="Italic"></Label>
</StackLayout>
</StackLayout>
</AbsoluteLayout>
</AbsoluteLayout>
</StackLayout>
Here is the TapGestureRecognizer function:
void OnImageNewsTappedGridRectangle(object sender, EventArgs args) {
OnArticleTapped(GridRectangleUrl);
}
Thanks for your help
Here is a sample of C# and XAML of the same page.
C#
public class MyPage : ContentPage
{
Button loginButton;
StackLayout layout;
public MyPage()
{
layout = new StackLayout
{
Children =
{
new Label { Text = "Please log in" },
new Label { Text = "Username", TextColor = Color.Black },
new Entry (),
new Label { Text = "Password", TextColor = Color.Black },
new Entry { IsPassword = true },
}
};
loginButton = new Button { Text = "Login" };
layout.Children.Add(loginButton);
Content = layout;
loginButton.Clicked += (sender, e) =>
{
Debug.WriteLine("Clicked !");
};
}
}
XAML Sample
<?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="Sample.MyPage">
<ContentPage.Content>
<StackLayout>
<Label Text="Please log in" />
<Label Text="Username" TextColor="Black" />
<Entry />
<Label Text="Password" TextColor="Black" />
<Entry IsPassword="true" />
<Button Text="Log in" Clicked="LoginButton_Clicked" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
I would take some time and learn Xamarin and the benefits of using XAML for the UI and behavior logic in C# code. One huge benefit is the preview support built in to Visual Studio. I think you will see (and other will agree) that this separation of concerns is the preferred way to develop.
There are some code to transform your code from xaml to C#, you can take a look:
This is your xaml code:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout
x:Name="GridRectangle"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="2">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="OnImageNewsTappedGridRectangle" />
</StackLayout.GestureRecognizers>
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Image
x:Name="GridRectangleImage"
AbsoluteLayout.LayoutBounds="1,1,1,1"
AbsoluteLayout.LayoutFlags="All"
Aspect="AspectFill"
Source="a11.jpg" />
<AbsoluteLayout
AbsoluteLayout.LayoutBounds="1,1,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="#66000000">
<StackLayout
AbsoluteLayout.LayoutBounds="1,1,1,1"
AbsoluteLayout.LayoutFlags="All"
BackgroundColor="Transparent"
Orientation="Vertical">
<StackLayout
Padding="3"
HorizontalOptions="StartAndExpand"
VerticalOptions="StartAndExpand">
<Label
x:Name="GridRectangleTitle"
FontAttributes="Bold"
FontSize="Medium"
Text="this is stacklayout1"
TextColor="White" />
</StackLayout>
<StackLayout
Padding="3"
HorizontalOptions="EndAndExpand"
VerticalOptions="EndAndExpand">
<Label
x:Name="GridRectangleProviderAndDate"
FontAttributes="Italic"
FontSize="Small"
Text="this is stacklayout2"
TextColor="White" />
</StackLayout>
</StackLayout>
</AbsoluteLayout>
</AbsoluteLayout>
</StackLayout>
</Grid>
This is your corresponding C # in the page constructor, you can try.
Grid grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
var GridRectangle = new StackLayout();
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) =>
{
// handle the tap
};
GridRectangle.GestureRecognizers.Add(tapGestureRecognizer);
var layout = new AbsoluteLayout() { HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.FillAndExpand };
var GridRectangleImage = new Image() { Source = "a11.jpg", Aspect = Aspect.AspectFill };
AbsoluteLayout.SetLayoutBounds(GridRectangleImage, new Rectangle(1, 1, 1, 1));
AbsoluteLayout.SetLayoutFlags(GridRectangleImage, AbsoluteLayoutFlags.All);
var layout2 = new AbsoluteLayout() { BackgroundColor = Color.FromHex("#66000000") };
AbsoluteLayout.SetLayoutBounds(layout2, new Rectangle(1, 1, 1, 1));
AbsoluteLayout.SetLayoutFlags(layout2, AbsoluteLayoutFlags.All);
var stacklayout1 = new StackLayout() { Orientation = StackOrientation.Vertical, BackgroundColor = Color.Transparent };
AbsoluteLayout.SetLayoutBounds(stacklayout1, new Rectangle(1, 1, 1, 1));
AbsoluteLayout.SetLayoutFlags(stacklayout1, AbsoluteLayoutFlags.All);
var stacklayout2 = new StackLayout() { HorizontalOptions = LayoutOptions.StartAndExpand, VerticalOptions = LayoutOptions.StartAndExpand, Padding = 3 };
var GridRectangleTitle = new Label() { Text = "this is stackalyout1", FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)), FontAttributes = FontAttributes.Bold, TextColor = Color.White };
stacklayout2.Children.Add(GridRectangleTitle);
var stacklayout3 = new StackLayout() { HorizontalOptions = LayoutOptions.EndAndExpand, VerticalOptions = LayoutOptions.EndAndExpand, Padding = 3 };
var GridRectangleProviderAndDate = new Label() { Text = "this is stackalyout2", FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)), FontAttributes = FontAttributes.Italic, TextColor = Color.White };
stacklayout3.Children.Add(GridRectangleProviderAndDate);
stacklayout1.Children.Add(stacklayout2);
stacklayout1.Children.Add(stacklayout3);
layout2.Children.Add(stacklayout1);
layout.Children.Add(GridRectangleImage);
layout.Children.Add(layout2);
GridRectangle.Children.Add(layout);
grid.Children.Add(GridRectangle, 0, 0);
Grid.SetColumnSpan(GridRectangle, 2);
this.Content = grid;
Gently, how can I achieve this in xaml? It must be pretty damn easy but can't wrap my mind around it :/
This is what I'm trying to achieve :
This is my view.xaml
<StackLayout x:Name="stackExample">
<StackLayout Margin="10,10,10,5" >
<Label Text="Info" />
<BoxView Color="#29abe2" WidthRequest ="100" HeightRequest="1" />
</StackLayout>
<StackLayout x:Name="optionsContentStack" >
</StackLayout>
</StackLayout>
this is my view.xaml.cs
foreach (var ex in example)
{
var labelHtmlInst = new Label { Text = ex.Info, FontSize = 15, TextColor = Color.FromHex("#222222"), HorizontalOptions = LayoutOptions.Center, VerticalOptions=LayoutOptions.Center, HorizontalTextAlignment = TextAlignment.Start };
optionsContentStack.Children.Add(labelHtmlInst);
var labelDs = new Label { Text = ex.Info, FontSize = 10, TextColor = Color.FromHex("#999999"), HorizontalOptions=LayoutOptions.Start, HorizontalTextAlignment = TextAlignment.Start, Margin = new Thickness(0, 0, 0, 10) };
optionsContentStack.Children.Add(labelDs);
var boxviewDs = new BoxView { Color = Color.FromHex("#f7931e"), WidthRequest = 100, HeightRequest = 1, HorizontalOptions = LayoutOptions.Start };
optionsContentStack.Children.Add(boxviewDs);
}
I have followed Gusman's advice and I positioned by layout in this order:
->StackLayout, VerticalOptions=FillAndExpand
->ScrollView, VerticalOptions=FillAndExpand
->RelativeLayout
->StackLayout
->StackLayout
->Button, VerticalOptions=EndAndExpand
Where I want my Button to be fixed on the bottom of my device view when scrolling throughout the whole layout. However, the view does not show the redeem button nor the full scroll bar. I'm not sure why those two elements are not displaying on the view.
How can I fix button on the bottom of the view when scrolling vertically on device?
Here's my latest code:
public StackLayout OffersSlideViewCarouselChild(Offer offer)
{
Image productImage = new Image
{
Source = ImageSource.FromUri(new Uri(offer.Image.Replace("https://", "http://"))),
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
HeightRequest = 300,
WidthRequest = 300,
Aspect = Aspect.AspectFit
};
var topStackLayout = new StackLayout
{
HorizontalOptions = LayoutOptions.CenterAndExpand,
VerticalOptions = LayoutOptions.Center,
};
topStackLayout.Children.Add(productImage);
StackLayout contentStackLayout = new StackLayout
{
Padding = new Thickness(16, 16, 16, 10),
Orientation = StackOrientation.Vertical,
HorizontalOptions = LayoutOptions.FillAndExpand,
};
var savedBtn = SavedButtonLayout(offer.IsSelected, offer.Id);
var redeemBtn = RedeemBtnLayout(offer.Id);
var timeRemainingLabel = TimeRemainingLayout(offer, offer.Id);
contentStackLayout.Children.Add(new UILabel(16) {
Text = offer.ProductName,
TextColor = ColorHelper.FromHex(CoreTheme.COLOR_OFFERCELL_PRODUCT_TEXT),
FontFamily = CoreTheme.FONT_FAMILY_DEFAULT_BOLD
});
contentStackLayout.Children.Add(new UILabel(14) {
Text = offer.LongRewardsMessage,
TextColor = ColorHelper.FromHex(CoreTheme.COLOR_DEAL_PAGE_LONG_REWARD_MESSAGE_RED),
FontFamily = CoreTheme.FONT_FAMILY_DEFAULT_BOLD
});
if (!string.IsNullOrEmpty(offer.PowerMessage)) {
var htmlText = string.Format("<html><body style='color:#9b9b9b'>{0}</body></html>", offer.PowerMessage.Replace(#"\", string.Empty));
var browser = new WebView() {
HeightRequest = (DeviceDisplaySettings.defaultheight > 600) ? 240 : 150,
Source = new HtmlWebViewSource() { Html = htmlText },
};
browser.Navigating += OnNavigating;
contentStackLayout.Children.Add(browser);
}
var mainRelLayout = new RelativeLayout();
mainRelLayout.Children.Add(savedBtn,
xConstraint: Constraint.Constant(0),
yConstraint: Constraint.Constant(0),
widthConstraint: Constraint.RelativeToParent((parent) =>
{
return parent.Width;
}),
heightConstraint: Constraint.RelativeToParent((parent) =>
{
return 40;
})
);
mainRelLayout.Children.Add(topStackLayout,
Constraint.RelativeToParent((parent) => { return (parent.Width - productImage.Width) / 2; }),
Constraint.RelativeToParent((parent) => { return parent.Y; })
);
mainRelLayout.Children.Add(timeRemainingLabel,
null,
Constraint.RelativeToView(topStackLayout, (parent, sibling) => { return sibling.Height; })
);
mainRelLayout.Children.Add(contentStackLayout,
null,
Constraint.RelativeToView(topStackLayout, (parent, sibling) => { return sibling.Height; })
);
var mainScrollView = new ScrollView()
{
VerticalOptions = LayoutOptions.FillAndExpand,
Orientation = ScrollOrientation.Vertical,
WidthRequest = DeviceDisplaySettings.defaultwidth,
HeightRequest = DeviceDisplaySettings.defaultheight,
Content = mainRelLayout
};
var mainStackLayout = new StackLayout()
{
Spacing = 0,
Padding = new Thickness(0, 0, 0, 0),
VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand,
Orientation = StackOrientation.Vertical,
Children = { mainScrollView, redeemBtn }
};
return mainStackLayout;
}
After looking at the wireframe you provided (http://imgur.com/wWBUNud), this is what I would use
(note that I am using XAML here to make the visual structure more obvious)
<?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="FormsSandbox.XamlPage">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollView Orientation="Vertical">
<!---Using StackLayout here to make sure scrolling works as
expected - but put your RelativeLayout content here instead -->
<StackLayout Spacing="0">
<BoxView BackgroundColor="Red" HeightRequest="50"/>
<BoxView BackgroundColor="Yellow" HeightRequest="100"/>
<BoxView BackgroundColor="Red" HeightRequest="50"/>
<BoxView BackgroundColor="Yellow" HeightRequest="100"/>
<BoxView BackgroundColor="Red" HeightRequest="50"/>
<BoxView BackgroundColor="Yellow" HeightRequest="100"/>
<BoxView BackgroundColor="Red" HeightRequest="50"/>
<BoxView BackgroundColor="Yellow" HeightRequest="100"/>
<BoxView BackgroundColor="Red" HeightRequest="50"/>
<BoxView BackgroundColor="Yellow" HeightRequest="100"/>
<BoxView BackgroundColor="Red" HeightRequest="50"/>
<BoxView BackgroundColor="Yellow" HeightRequest="100"/>
<BoxView BackgroundColor="Red" HeightRequest="50"/>
</StackLayout>
</ScrollView>
<Button Grid.Row="1" Text="REDEEM"/>
</Grid>
</ContentPage>
For the aclaration I understand you want something like this:
->ScrollView
->RelativeLayout
->StackLayout
->StackLayout
->Button
But want to fix the button on the bottom even when the page is scrolled.
With that structure is just impossible to do it but it's very easy to fix it with an structure like this:
->StackLayout, VerticalOptions=FillAndExpand
->ScrollView, VerticalOptions=FillAndExpand
->RelativeLayout
->StackLayout
->StackLayout
->Button, VerticalOptions=EndAndExpand
With that structure you will have a root StackLayout where you nest an ScrollView which will fill all the screen except for the space taken by the Button which will stick to the bottom of the screen.
Hope it makes sense.
Cheers.