Xamarin Forms ScrollView displays blank screen - xaml

The following XAML shows my page just fine, until I added the ScrollView , now it just displays a blank screen.
Can anyone spot anything obvious with this? I suspect it my be because I'm setting the height of the grid within the ScrollView but I'm not sure
<ContentPage.Content>
<ScrollView>
<Grid BackgroundColor="#ede8db" x:Name="articleGrid" >
<Grid.RowDefinitions>
<RowDefinition Height="47.5*" />
<RowDefinition Height="5*" />
<RowDefinition Height="47.5*" />
</Grid.RowDefinitions>
<ratio:ContentRatioContainer Grid.Row="0" x:Name="imgContainer">
<Image Aspect="AspectFill" Source="KevingroveCarouselImg.png" AbsoluteLayout.LayoutBounds="1,1,1,1" AbsoluteLayout.LayoutFlags="All" x:Name="bigImg"
HeightRequest="{artina:OnOrientationDouble PortraitPhone=880, LandscapePhone=125, PortraitTablet=600, LandscapeTablet=400 }" Grid.Row="0"/>
</ratio:ContentRatioContainer>
<artina:Button Margin="10,10,10,10" x:Name="ImgZoom" Clicked="EnlargeImage" HorizontalOptions="End" VerticalOptions="Start" Image="IncreaseImageIcon.png" BackgroundColor="Transparent" HeightRequest="30" WidthRequest="30"/>
<StackLayout Grid.Row="1" Orientation="Horizontal" BackgroundColor="#ede8db" Margin="0" Padding="30,0,30,0" x:Name="iconStack" HorizontalOptions="FillAndExpand" >
<Label HorizontalTextAlignment="Center" Text="{x:Static ratio:FontAwesome.WIFI}" Style="{StaticResource FontIcon}" TextColor="Black" FontSize="{artina:OnOrientationDouble PortraitPhone=25, LandscapePhone=18, PortraitTablet=30, LandscapeTablet=20 }" />
<Label HorizontalTextAlignment="Center" Text="{x:Static ratio:FontAwesome.CAMERA}" Style="{StaticResource FontIcon}" TextColor="Black" FontSize="{artina:OnOrientationDouble PortraitPhone=25, LandscapePhone=18, PortraitTablet=30, LandscapeTablet=20 }" />
<Label HorizontalTextAlignment="Center" Text="{x:Static ratio:FontAwesome.MAP}" Style="{StaticResource FontIcon}" TextColor="Black" FontSize="{artina:OnOrientationDouble PortraitPhone=25, LandscapePhone=18, PortraitTablet=30, LandscapeTablet=20 }" />
<Label x:Name="expand" HorizontalTextAlignment="Center" HorizontalOptions="EndAndExpand" Text="{x:Static ratio:FontAwesome.ARROW_DOWN}" Style="{StaticResource FontIcon}" TextColor="Black" FontSize="{artina:OnOrientationDouble PortraitPhone=25, LandscapePhone=18, PortraitTablet=30, LandscapeTablet=20 }" />
</StackLayout>
<StackLayout Grid.Row="2" x:Name="articleInfo" Padding="30,0,30,0" >
<StackLayout x:Name="TopLayout" Opacity="0.0">
<StackLayout Orientation="Horizontal">
<Label HorizontalTextAlignment="Center" Text="{x:Static ratio:FontAwesome.MAP_MARKER}" Style="{StaticResource FontIcon}" TextColor="Black" FontSize="30" />
<Label Text="Address" VerticalOptions="Center" HorizontalOptions="StartAndExpand" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label HorizontalTextAlignment="Center" Text="{x:Static ratio:FontAwesome.CLOCK_O}" Style="{StaticResource FontIcon}" TextColor="Black" FontSize="30" />
<Label Text="Openening Times" VerticalOptions="Center" HorizontalOptions="StartAndExpand" />
</StackLayout>
<StackLayout x:Name="EmptySpaceStack" HeightRequest="80" />
<StackLayout x:Name="txt" >
<Label x:Name="header" Text="HEADER" Style="{ StaticResource HeaderStyle }" />
<Label x:Name="description" Text="TEST" FontSize="Large" />
<Label x:Name="articleTxt" Text="BLAH..." FontSize="Medium"/>
</StackLayout>
</StackLayout>
</StackLayout>
</Grid>
</ScrollView>
</ContentPage.Content>
UPDATE
looks like it's the ContentRationContainer that causes the problem, just to figure out why...
public class ContentRatioContainer : ContentView
{
public double ratio;
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
var width = Application.Current.MainPage.Width;
var height = Application.Current.MainPage.Height;
if (Device.Idiom == TargetIdiom.Phone)
{
ratio = Convert.ToDouble(Resx.AppResources.ImageRatioContentPhone);
}
if (Device.Idiom == TargetIdiom.Tablet)
{
if (width > height)
{
ratio = Convert.ToDouble(Resx.AppResources.ImageRatioContentTabL);
}
else
{
ratio = Convert.ToDouble(Resx.AppResources.ImageRatioContentTabP);
}
}
return new SizeRequest(new Size(widthConstraint, widthConstraint * ratio));
}
public static BindableProperty ContentRatioProperty = BindableProperty.Create(nameof(ContentRatio), typeof(double), typeof(ContentRatioContainer), (double)1);
public double ContentRatio
{
get { return (double)this.GetValue(ContentRatioProperty); }
set { this.SetValue(ContentRatioProperty, value); }
}
}

Related

xamarin form design in list view

How could I achieve the following , it is a list of many items. on it
Design Goal
and this is my code :
<Label Text = "Today Appointments :" TextColor = "#2196f3" WidthRequest = "200"
HeightRequest="50" FontSize = "Small" Margin = "13" FontAttributes = "Bold" ></Label >
<ListView HasUnevenRows="True" ItemsSource="{Binding Appoitments}" RowHeight="5" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid RowDefinitions="Auto,Auto,Auto">
<Frame
BorderColor="Gray"
CornerRadius="5"
Padding="8"
HasShadow="True"
>
<StackLayout Orientation="Vertical" Padding="5">
<Label Grid.Row="0" Text="{Binding AppointmentPatientName}" TextColor="Black" FontSize="Small" FontAttributes="Bold" Margin="20" />
<Label Grid.Row="0" Grid.Column="1" Text="{Binding AppointmentDate}" TextColor="Black" FontSize="Small" FontAttributes="Bold" Margin="20" />
</StackLayout>
</Frame>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
A CollectionView offers the option to group your items in the list and create a Header for your group.
Enable IsGrouped property :
<CollectionView IsGrouped="true" />
then add
<CollectionView.GroupHeaderTemplate>
<DataTemplate>
//Your Group Header here...
<Label Text="{Binding AppoitmentsId}"
BackgroundColor="LightGray"
FontSize="Large"
FontAttributes="Bold" />
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
Follow this Link

First-time user onboarding with Xamarin.Forms

I am implementing a first-time user onboarding in a Xamarin.Forms application like the one on the image below:
Please, how can I quickly do that?
Thank you in advance.
Do you want to achieve the result like following GIF?
You can use CarouselView and IndicatorView to achieve it.
Here is layout code.I dont adjust the layout like yours, you can adjust it by yourself, If you want to make Next and Skip Button over float the CarouselView, you can use AbsoluteLayout
<StackLayout Margin="10">
<CarouselView x:Name="myCarouselView" ItemsSource="{Binding Monkeys}"
IndicatorView="indicatorView">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="50"
HeightRequest="300"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<StackLayout>
<Label Text="{Binding Name}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Image Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="150"
WidthRequest="150"
HorizontalOptions="Center" />
<Label Text="{Binding Location}"
HorizontalOptions="Center" />
<Label Text="{Binding Details}"
FontAttributes="Italic"
HorizontalOptions="Center"
MaxLines="5"
LineBreakMode="TailTruncation" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Skip" Grid.Column="0" BackgroundColor="Transparent" Clicked="Button_Clicked"></Button>
<Button Text="Next" Grid.Column="1" BackgroundColor="Transparent" Clicked="Button_Clicked_1"></Button>
</Grid>
<IndicatorView x:Name="indicatorView"
MaximumVisible="6"
Margin="0,0,0,40"
IndicatorColor="LightGray"
SelectedIndicatorColor="DarkGray"
HorizontalOptions="Center" />
</StackLayout>
Here is layout bakground code.
public partial class BasicIndicatorViewPage : ContentPage
{
int monkeyCount;
public BasicIndicatorViewPage()
{
InitializeComponent();
MonkeysViewModel monkeysViewModel= new MonkeysViewModel();
monkeyCount = monkeysViewModel.Monkeys.Count;
BindingContext = monkeysViewModel;
}
private void Button_Clicked(object sender, System.EventArgs e)
{
Navigation.PushAsync(new Page1());
Navigation.RemovePage(this);
}
private void Button_Clicked_1(object sender, System.EventArgs e)
{
if (myCarouselView.Position < monkeyCount-1)
{
myCarouselView.Position += 1;
}
else
{
Navigation.PushAsync(new Page1());
Navigation.RemovePage(this);
}
}
}
Here is my demo, you can download it.
https://github.com/851265601/XFormsCarouselView-IndicatorViewLoginPage
If you want to put the indicatorView and Button in the same line like this screenshot.
You can use this layout(indicatorView to the Grid).
<StackLayout Margin="10">
<CarouselView x:Name="myCarouselView" ItemsSource="{Binding Monkeys}"
IndicatorView="indicatorView">
<CarouselView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Frame HasShadow="True"
BorderColor="DarkGray"
CornerRadius="5"
Margin="50"
HeightRequest="300"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<StackLayout>
<Label Text="{Binding Name}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="Center" />
<Image Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="150"
WidthRequest="150"
HorizontalOptions="Center" />
<Label Text="{Binding Location}"
HorizontalOptions="Center" />
<Label Text="{Binding Details}"
FontAttributes="Italic"
HorizontalOptions="Center"
MaxLines="5"
LineBreakMode="TailTruncation" />
</StackLayout>
</Frame>
</StackLayout>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Skip" Grid.Column="0" BackgroundColor="Transparent" Clicked="Button_Clicked"></Button>
<IndicatorView x:Name="indicatorView"
MaximumVisible="6"
IndicatorColor="LightGray"
SelectedIndicatorColor="DarkGray"
HorizontalOptions="Center" Grid.Column="1" />
<Button Text="Next" Grid.Column="2" BackgroundColor="Transparent" Clicked="Button_Clicked_1"></Button>
</Grid>
</StackLayout>
You could use the offical Xamarin.Forms CarouselView but that's still in preview. You could also potentially look at the Sharpnado's solution with HorizontalListView. Your third option would be to use Alex Rainman's CarouselView.

Xamarin Forms Carousel view issue with binding

Hello I’m having an issue with binding a list of string to my Carousel View
First I have a list of an object I get from my server
public class PostObject
{
public string PostOwner { get; set; }
public string Id { get; set; }
public string Post { get; set; }
public string ProfileImage { get; set; }
public List<string> PostImages { get; set; }
}
List<PostObject> posts = new List<PostObject>();
This works as I expected.
Next I have a card view I created and within the card view I want to have a Carousel View.
So I have setup my Xaml like this (omitting the parts that works for clarity)
<?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:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin"
NavigationPage.HasNavigationBar="True"
NavigationPage.HasBackButton="False"
NavigationPage.BackButtonTitle="Back"
Title="amici"
x:Class="amici.Posts">
<NavigationPage.TitleView>
<StackLayout Orientation="Horizontal" VerticalOptions="Center" Spacing="10" >
<Label x:Name="GroupTitle" TextColor="White" FontSize="Medium"/>
</StackLayout>
</NavigationPage.TitleView>
<ContentPage.ToolbarItems>
<ToolbarItem Name="iconexample" Icon="settings.png" Priority="0" Order="Primary" />
</ContentPage.ToolbarItems>
<ContentPage.Content>
<StackLayout>
<ListView x:Name="ItemsListView"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement">
<!--ItemSelected="OnItemSelected"-->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<StackLayout Padding="10">
<Frame x:Name="myframe" HasShadow="True" >
<Grid HorizontalOptions="FillAndExpand" RowSpacing="0" ColumnSpacing="0" >
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="20" />
<RowDefinition Height="20" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Text="{Binding PostOwner}" LineBreakMode="WordWrap" Font="Bold,16" />
<controls:CircleImage Grid.Row="0" Margin="10" BorderColor="white" BorderThickness="1" VerticalOptions="Start" HorizontalOptions="Start" Source="{Binding ProfileImage}" Aspect="AspectFit">
<controls:CircleImage.WidthRequest>
<OnPlatform x:TypeArguments="x:Double">
<On Platform="Android, iOS">65</On>
</OnPlatform>
</controls:CircleImage.WidthRequest>
<controls:CircleImage.HeightRequest>
<OnPlatform x:TypeArguments="x:Double">
<On Platform="Android, iOS">65</On>
</OnPlatform>
</controls:CircleImage.HeightRequest>
</controls:CircleImage>
<Label Grid.Row="1" Text="{Binding Post}" LineBreakMode="WordWrap" Font="Bold,16" />
<CarouselView x:Name="PostImages" Grid.Row="2" ItemsSource="{Binding PostImages}">
<CarouselView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding .}" Aspect="AspectFill" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
<!--<Image Grid.Row="2" Source="{Binding ImageURL}" Aspect="AspectFill" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />-->
<BoxView Grid.Row="3" BackgroundColor="black" HeightRequest="1" HorizontalOptions="FillAndExpand"/>
<StackLayout Grid.Row="4" Orientation="Horizontal" >
<Label Text="Likes: " LineBreakMode="NoWrap" Font="Bold,14" />
<Label Text="0" LineBreakMode="NoWrap" FontSize="14" />
</StackLayout>
<StackLayout Grid.Row="5" Orientation="Horizontal" >
<Label Text="Comments: " LineBreakMode="NoWrap" Font="Bold,14" HorizontalOptions="End" />
<Label Text="0" HorizontalOptions="End" LineBreakMode="NoWrap" FontSize="14" />
</StackLayout>
<!--<Label Grid.Row="2" Text="{Binding OwnerFullName}" LineBreakMode="NoWrap" FontSize="16" />-->
</Grid>
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
In my code behind I have this
public Posts (GroupInfo ginfo)
{
InitializeComponent ();
GroupTitle.Text = ginfo.Title;
CurrentGroupInfo = ginfo;
GetDataPosts();
ItemsListView.RefreshCommand = new Command(() => {
GetDataPosts();
ItemsListView.IsRefreshing = false;
});
}
public void GetDataPosts()
{
try
{
string apikey = Application.Current.Properties["api"].ToString();
ItemsListView.ItemsSource = null;
posts.Clear();
if (RestController.GetMyPostData(ref posts, CurrentGroupInfo.Id.ToString(), apikey))
{
ItemsListView.ItemsSource = posts;
}
}
catch(Exception e)
{
Debug.WriteLine(e.Message);
}
}
now up to this point everything works and no errors but when the app goes to render the page I get a error
System.TypeInitializationException: The type initializer for 'Xamarin.Forms.ItemsView' threw an exception.
which I trace back to the Carousel View. When I comment out the Carousel View the it works. so I'm thinking I can't bind OR use the Carousel View in the way I thought?
The CarouselView used to be a plugin that has now become part of Xamarin.Forms effective with version 4. You can use an earlier XF version but you will need to get this plugin, add assembly references to your XAML and put initialization code in your platform specific projects.
Alternatively, you could upgrade to Xamarin.Forms 4
Even though you can see the Carousel View on Xamarin.Forms 3.6.0.344457, it only defines an interface there. There're no implementations and properties in the Carousel View Class.
You can only utilize it under Xamarin.Forms 4.0. As it is still a preview version now, there're some limitations. See my post here: https://stackoverflow.com/a/56235795/8354952 for more information.

How to make 3 column Xamarin.Forms FlexLayout with expanding center column and variable width left/right columns?

I'm trying to create a FlexLayout in Xamarin.Forms that will allow me to have the left and right columns be a variable width, and have the center column (and its contents) fill the remaining space and be centered on the screen.
Here is my current code, and here is what it's producing. Notice that "CENTER TEXT" in blue is centered within its StackLayout, but the StackLayout is not centered on the screen since the left and right columns have different widths.
Is FlexLayout a good choice for this, or should I use Grid or something else? Ideally, each column will expand to fit its content, with the center column's content being centered on the screen.
Note that the contents of each column is dynamic, so the widths of the left and right columns is also dynamic.
Thank you!
Code:
<FlexLayout x:Name="titleBar"
MinimumHeightRequest="40"
Padding="10"
JustifyContent="SpaceBetween"
AlignItems="Center"
AlignContent="Center">
<StackLayout x:Name="leftActionButton"
VerticalOptions="Center"
BackgroundColor="Red"
Orientation="Horizontal">
<Image x:Name="leftActionImg"
Margin="0, 0, 5, 0"
HeightRequest="40"
VerticalOptions="Center" />
<Label x:Name="leftActionLabel"
VerticalOptions="Center" />
</StackLayout>
<StackLayout VerticalOptions="Center"
BackgroundColor="Blue"
FlexLayout.Grow="1"
FlexLayout.Shrink="0">
<Label x:Name="title"
HorizontalTextAlignment="Center"/>
</StackLayout>
<StackLayout x:Name="rightActionButton"
BackgroundColor="Yellow"
VerticalOptions="Center"
Orientation="Horizontal">
<Label x:Name="rightActionLabel"
VerticalOptions="Center"
HorizontalOptions="End"
HorizontalTextAlignment="End" />
<Image x:Name="rightActionImg"
HeightRequest="40"
VerticalOptions="Center"
HorizontalOptions="End" />
</StackLayout>
</FlexLayout>
Results:
I was struggling with the same problem recently. So I was investing a day to find a solution. The result is disillusioning and I wouldn't call it a proper solution. I'm posting my thoughts here, because I couldn't find anything similar on the net.
I created a component which is responsible for balancing all three columns: It subscribes to width changes of the left and right column and propagates the relative difference to the center column.
The center column takes the relative difference as correction by applying a padding.
MainPage: In the Resources part you see that I'm declaring an instance of ColumnBalancer. Later I subscribe Width changes to ColumnBalancer, so ColumnBalancer gets to known when the very left and very right column (content, actually) changes. The PaddingOffset binding is retrieved from the same ColumnBalancer instance whenever the Width values have changed.
<ContentPage
x:Class="App7863.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:cb="clr-namespace:ColumnBalancing"
mc:Ignorable="d">
<ContentPage.Resources>
<ResourceDictionary>
<cb:ColumnBalancer x:Key="ColumnBalancer" x:Name="ColumnBalancer" />
</ResourceDictionary>
</ContentPage.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Header -->
<Grid
Grid.Row="0"
Padding="10"
BackgroundColor="LightGray">
<Grid.RowDefinitions>
<RowDefinition Height="39" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- Navigate Back Button -->
<Label
Grid.Column="0"
Width="{Binding Source={x:Reference ColumnBalancer}, Path=ReferenceWidthLeft}"
Text="<"
FontSize="20"
BackgroundColor="Magenta"
WidthRequest="39"
HeightRequest="39"
VerticalOptions="CenterAndExpand"
VerticalTextAlignment="Center"
HorizontalOptions="CenterAndExpand"
HorizontalTextAlignment="Center" />
<!-- Page Title -->
<StackLayout
Grid.Column="1"
Margin="0"
Padding="{Binding Source={x:Reference ColumnBalancer}, Path=PaddingOffset}"
BackgroundColor="LightYellow"
Spacing="0">
<Label
Text="Center Title"
FontSize="20"
BackgroundColor="Magenta"
HeightRequest="39"
VerticalOptions="CenterAndExpand"
VerticalTextAlignment="Center"
HorizontalOptions="CenterAndExpand"
HorizontalTextAlignment="Center"
LineBreakMode="TailTruncation" />
</StackLayout>
<!-- Toolbar Items -->
<StackLayout
Grid.Column="2"
Width="{Binding Source={x:Reference ColumnBalancer}, Path=ReferenceWidthRight}"
Margin="0"
Padding="0"
BackgroundColor="LightGreen"
Orientation="Horizontal"
Spacing="6">
<Label
x:Name="ToolbarT1"
Text="T1"
FontSize="20"
BackgroundColor="Green"
WidthRequest="39"
HeightRequest="39"
VerticalOptions="CenterAndExpand"
VerticalTextAlignment="Center"
HorizontalOptions="CenterAndExpand"
HorizontalTextAlignment="Center"
IsVisible="False" />
<Label
x:Name="ToolbarT2"
Text="T2"
FontSize="20"
BackgroundColor="Green"
WidthRequest="39"
HeightRequest="39"
VerticalOptions="CenterAndExpand"
VerticalTextAlignment="Center"
HorizontalOptions="CenterAndExpand"
HorizontalTextAlignment="Center"
IsVisible="False" />
</StackLayout>
<Label
Grid.Row="2"
Grid.ColumnSpan="3"
Text="Subtitle with more info"
FontSize="20"
BackgroundColor="LightBlue"
HeightRequest="39"
VerticalOptions="CenterAndExpand"
VerticalTextAlignment="Center"
HorizontalOptions="StartAndExpand"
HorizontalTextAlignment="Start" />
</Grid>
<!-- Content -->
<Grid
Grid.Row="1"
Padding="40"
BackgroundColor="LightCoral">
<StackLayout BackgroundColor="LightBlue">
<Button Text="Toogle T1" Clicked="Button_ToogleT1" />
<Button Text="Toogle T2" Clicked="Button_ToogleT2" />
</StackLayout>
</Grid>
</Grid>
</ContentPage>
ColumnBalancer: Exposes a ReferenceWidthLeft and ReferenceWidthRight which take the Width values from the left resp. right column content. Whenever the ReferenceWidth* properties change, a new PaddingOffset is set.
public class ColumnBalancer : BindableObject
{
public static readonly BindableProperty PaddingOffsetProperty = BindableProperty.Create(
nameof(PaddingOffset),
typeof(Thickness),
typeof(ColumnBalancer),
default(Thickness),
BindingMode.OneWay);
public Thickness PaddingOffset
{
get => (Thickness)this.GetValue(PaddingOffsetProperty);
set => this.SetValue(PaddingOffsetProperty, value);
}
public static readonly BindableProperty ReferenceWidthRightProperty = BindableProperty.Create(
nameof(ReferenceWidthRight),
typeof(double),
typeof(ColumnBalancer),
default(double),
BindingMode.OneWayToSource,
null,
OnReferenceWidthRightPropertyChanged);
public double ReferenceWidthRight
{
get => (double)this.GetValue(ReferenceWidthRightProperty);
set => this.SetValue(ReferenceWidthRightProperty, value);
}
public static readonly BindableProperty ReferenceWidthLeftProperty = BindableProperty.Create(
nameof(ReferenceWidthLeft),
typeof(double),
typeof(ColumnBalancer),
default(double),
BindingMode.OneWayToSource,
null,
OnReferenceWidthLeftPropertyChanged);
public double ReferenceWidthLeft
{
get => (double)this.GetValue(ReferenceWidthLeftProperty);
set => this.SetValue(ReferenceWidthLeftProperty, value);
}
private static void OnReferenceWidthLeftPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
{
if (!(bindable is ColumnBalancer columnBalancer) || !(newvalue is double newLeftValue && newLeftValue >= 0))
{
return;
}
UpdatePaddingOffset(columnBalancer, newLeftValue, columnBalancer.ReferenceWidthRight);
}
private static void OnReferenceWidthRightPropertyChanged(BindableObject bindable, object oldvalue, object newvalue)
{
if (!(bindable is ColumnBalancer columnBalancer) || !(newvalue is double newRightValue && newRightValue >= 0))
{
return;
}
UpdatePaddingOffset(columnBalancer, columnBalancer.ReferenceWidthLeft, newRightValue);
}
private static void UpdatePaddingOffset(ColumnBalancer columnBalancer, double left, double right)
{
if (left < 0)
{
left = 0;
}
if (right < 0)
{
right = 0;
}
var relativePadding = Math.Abs(left - right);
if (right > left)
{
columnBalancer.PaddingOffset = new Thickness(relativePadding, 0, 0, 0);
}
else
{
columnBalancer.PaddingOffset = new Thickness(0, 0, relativePadding, 0);
}
}
}
I was able to get this to work by using a 2-column grid and overlaying the "center" column on top by using Grid.ColumnSpan="2".
I realize this has the potential for the content in the center to overlap the content on the left and right, but I'm OK with working around this limitation if that's the best I can do. Still welcome other, more robust suggestions, though!
<Grid x:Name="titleBar"
MinimumHeightRequest="40"
Padding="10"
HorizontalOptions="FillAndExpand">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout x:Name="leftActionButton"
VerticalOptions="Center"
Orientation="Horizontal"
HorizontalOptions="Start"
Grid.Column="0">
<Image x:Name="leftActionImg"
Margin="0, 0, 5, 0"
HeightRequest="40"
VerticalOptions="Center" />
<Label x:Name="leftActionLabel"
VerticalOptions="Center" />
</StackLayout>
<StackLayout x:Name="rightActionButton"
VerticalOptions="Center"
HorizontalOptions="End"
Orientation="Horizontal"
Grid.Column="1">
<Label x:Name="rightActionLabel"
VerticalOptions="Center"
HorizontalOptions="End"
HorizontalTextAlignment="End" />
<Image x:Name="rightActionImg"
HeightRequest="40"
VerticalOptions="Center"
HorizontalOptions="End" />
</StackLayout>
<StackLayout VerticalOptions="Center"
HorizontalOptions="CenterAndExpand"
Grid.Column="0"
Grid.ColumnSpan="2">
<Label x:Name="title"
HorizontalTextAlignment="Center"/>
</StackLayout>
</Grid>

Xamarin - slide element within Frame outside of view

Not really sure how to properly describe my problem using correct wording as I'm new to Xamarin and Xaml.
I have a Frame with several StackLayouts within and I want to slide a specific StackLayout outside the Frame without showing it outside the Frame.
I can currently do this with:
XAML:
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:XLabs.Forms.Controls;assembly=XLabs.Forms"
xmlns:mr="clr-namespace:MR.Gestures;assembly=MR.Gestures"
x:Class="iRemote.UI.Maps.LocationFinderMap"
xmlns:map="clr-namespace:iRemote.Location"
Title="Location Finder">
<Frame HasShadow="true" OutlineColor="Color.Black" WidthRequest="700" HeightRequest="300" Padding="3"
BackgroundColor="White">
<mr:StackLayout x:Name="sl_main" Padding="2" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"
Orientation="Horizontal" WidthRequest="200">
<StackLayout HorizontalOptions="Start" Orientation="Vertical">
<StackLayout HorizontalOptions="FillAndExpand" Orientation="Horizontal">
<Label Text="Parcel #" />
<Entry x:Name="txtParcel" WidthRequest="100" />
<Label HorizontalOptions="FillAndExpand" />
<Button x:Name="btnClose" BackgroundColor="#0786a3" BorderRadius="30" TextColor="White"
Text="Close" HorizontalOptions="End" />
</StackLayout>
<StackLayout HorizontalOptions="FillAndExpand" Orientation="Horizontal">
<Label Text="Meter #" />
<Entry x:Name="txtMeter" WidthRequest="100" />
</StackLayout>
<StackLayout HorizontalOptions="FillAndExpand" Orientation="Horizontal">
<SearchBar x:Name="search" Placeholder="Search" />
</StackLayout>
<StackLayout Padding="2" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout HorizontalOptions="FillAndExpand">
<mr:Image x:Name="img_map" Source="down" HeightRequest="19" WidthRequest="32" />
</StackLayout>
</StackLayout>
</StackLayout>
<StackLayout x:Name="sl_map" Padding="2" HorizontalOptions="FillAndExpand" HeightRequest="5"
VerticalOptions="FillAndExpand" IsVisible="true" WidthRequest="300">
<map:ExtendedMap
BackgroundColor="Blue"
x:Name="MP"
IsShowingUser="true"
MapType="Street" />
</StackLayout>
</mr:StackLayout>
</Frame>
</ContentPage>
Code-Behind:
if (panelShowing)
{
var rect = new Rectangle(this.Width - sl_map.Width, sl_map.Y, sl_map.Width, sl_map.Height);
sl_map.LayoutTo(rect, 250, Easing.CubicIn);
}
else
{
var rect = new Rectangle(this.Width + sl_map.Width - 40, sl_map.Y, sl_map.Width, sl_map.Height);
sl_map.LayoutTo(rect, 200, Easing.CubicOut);
}
However, sl_map simply just shows outside the frame. I want it to not be visible as it crosses the border of the frame. I hope that's clear enough. Again, sorry if I'm not using the correct terminology. I'm a WinForms guy.