When layin out this form, I want a header the size of its content, footer the size of the content, and a middle that expands to take up the rest. Easy in XAML/UWP. But in Xamarin Forms when the ScrollView content has data it floats and overlays the top and bottom. Also when I drag/scroll the ScrollView it can go to the top of the screen. How to dock the scrollview properly so I have a scrolling middle region? Thx...
Pictures and XAML layout below....
<?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="BaseProject.MainPage">
<Label Text="{Binding MainText}" VerticalOptions="Center" HorizontalOptions="Center" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TableView Grid.Row="0" Intent="Settings" BackgroundColor="Blue" HeightRequest="150" >
<TableSection Title="Search">
<ViewCell>
<Button x:Name="Button_Search" Text="Go"/>
</ViewCell>
<EntryCell x:Name="Entry_Cell_SearchFor" />
</TableSection>
</TableView>
<ScrollView Grid.Row="1" VerticalOptions="FillAndExpand" Orientation="Vertical">
<StackLayout BackgroundColor="Red" >
<Label Text="body" x:Name="Label_Body" BackgroundColor="Yellow" />
</StackLayout>
</ScrollView>
<StackLayout Grid.Row="2">
<Label Text="footer"/>
</StackLayout>
</Grid>
</ContentPage>
Set IsClippedToBounds property as true of ScrollView
Related
I have a StackLayout with a Frame, ScrollView & Button as it's child controls.
When the ScrollView content is beyond a certain Height, the ScrollView seems to push the Frame above it, squashing it. I would expect that the ScrollView as a container not push upwards the view above it, but contain its content within it.
Frame - red circle, ScrollView - Blue, ScrollView's content - light blue, Button - green
EXPECTED
<?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="Class">
<ContentPage.Content>
<StackLayout
VerticalOptions="FillAndExpand"
Orientation="Vertical">
<Frame
Padding="0"
HeightRequest="60"
WidthRequest="60"
VerticalOptions="Center"
HorizontalOptions="Center"
CornerRadius="30"
BackgroundColor="Red"/>
<ScrollView
Background="Blue"
VerticalOptions="FillAndExpand">
<StackLayout
Margin="20,5,20,0"
BackgroundColor="LightBlue"
HeightRequest="150"/>
</ScrollView>
<Button
VerticalOptions="End"
Text="Next"
BackgroundColor="Green"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Ouputs (Which is what i expect):
Then if i change the ScrollView's StackLayout content's height to 950, it then squashes the content above and it looks as below:
Why is the ScrollView pushing upwards, even when the Frame has an assigned HeightRequest. How can i resolve this?
Why is the ScrollView pushing upwards, even when the Frame has an assigned HeightRequest.
From ScrollView as a child layout, a ScrollView will often be the child of a StackLayout. A ScrollView requires a specific height to compute the difference between the height of its content and its own height, with the difference being the amount that the ScrollView can scroll its content.
So you can assign specific height to Scrollview.
<StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand">
<Frame
Padding="0"
BackgroundColor="Red"
CornerRadius="30"
HeightRequest="60"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="60" />
<ScrollView
Background="Blue"
HeightRequest="150"
VerticalOptions="FillAndExpand">
<StackLayout
Margin="20,5,20,0"
BackgroundColor="LightBlue"
HeightRequest="950" />
</ScrollView>
<Button
BackgroundColor="Green"
Text="Next"
VerticalOptions="End" />
</StackLayout>
Another way is to use Gird to assign specific height for Scrollview.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Frame
Padding="0"
BackgroundColor="Red"
CornerRadius="30"
HeightRequest="60"
HorizontalOptions="Center"
VerticalOptions="Center"
WidthRequest="60" />
<ScrollView
Grid.Row="1"
Background="Blue"
VerticalOptions="FillAndExpand">
<StackLayout
Margin="20,5,20,0"
BackgroundColor="LightBlue"
HeightRequest="950" />
</ScrollView>
<Button
Grid.Row="2"
BackgroundColor="Green"
Text="Next"
VerticalOptions="End" />
</Grid>
I work on a Xamarin.Forms.Shell app containing 4 tabs.
On the main tab, I have:
a TitleView containing the logo of the company
s ScrollView containing an Image as Header
a ScrollView containing the main content, that can cover the Header to be fully visible
The XAML looks like this:
<?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="AvilaShellAppSample.Views.HomePage"
Shell.NavBarHasShadow="False"
Shell.NavBarIsVisible="True"
x:Name="homePage">
<!-- TitleView -->
<Shell.TitleView >
<Grid>
<ffimageloadingsvg:SvgCachedImage Source="resource://ShellAppSample.Resources.blackLogoTitle.svg"
DownsampleHeight="6"
HeightRequest="45"/>
</Grid>
</Shell.TitleView>
<ContentPage.BindingContext>
<vm:HomeViewModel />
</ContentPage.BindingContext>
<ContentPage.Content>
<Grid RowSpacing="0"
BackgroundColor="{StaticResource Gray-050}"
Margin="0,0,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<!-- Header ScrollView : Image -->
<ScrollView>
<ContentView x:Name="headerView"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Header Image -->
<ffimageloading:CachedImage x:Name="headerImage"
Grid.Row="0"
Aspect="AspectFill"
BackgroundColor="{DynamicResource Gray-200}"
DownsampleToViewSize="true"
HeightRequest="280"
HorizontalOptions="FillAndExpand"
VerticalOptions="Start"
Source="resource://ShellAppSample.Resources.indoor.jpg">
</ffimageloading:CachedImage>
</Grid>
</ContentView>
</ScrollView>
<!-- Content ScrollView -->
<ScrollView>
<ctrl:ParallaxScrollView HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
ParallaxHeaderView="{x:Reference headerView}"
LogoHeaderView="{x:Reference logoHeaderView}"
HiddenView="{x:Reference hiddenView}"
MainPage="{Binding homePage}">
<Grid ColumnSpacing="0"
RowSpacing="0"
VerticalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="220" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Content -->
</Grid>
</ctrl:ParallaxScrollView>
</ScrollView>
</Grid>
</Grid>
</ContentPage.Content>
</ContentPage>
I would like to display the header Image over the NavigationBar/StatusBar by default: so the NavigationBar would be hidden, and the StatusBar background would be the Image header.
Then I would like to display the default NavigationBar/StatusBar only when the content cover the half of the Header: so the NavigationBar would be visible, and the StatusBar background would be the default background.
But I didn't found any way to access to the Shell.NavBarIsVisible property or to the Shell.TitleView in code-behind.
So I would like to know is this is possible?
You need to use the exposed methods in order to set the properties SetNavBarIsVisible() and SetTitleView()
Disabeling the navigation bar for a page in it code-behind:
Shell.SetNavBarIsVisible(this, false);
Setting a custom TitleView for a page in it code-behind:
Label r = new Label();
r.Text = "Hello World";
Shell.SetTitleView(this, (View)r);
My code below creates what is shown in the picture below where the label's text is from an API I am calling. Also the drawing canvas is taken from https://github.com/xamarin/xamarin-forms-samples/tree/master/SkiaSharpForms/Demos/Demos/SkiaSharpFormsDemos. I was wondering how to make the drawing canvas more larger in height? Thank you.
<?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:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
xmlns:tt="clr-namespace:TouchTracking"
x:Class="MathKumu.Pages.WorkPage">
<ContentPage.Content>
<StackLayout>
<Label Text="{Binding EquationString}" />
<Entry Placeholder="Put Answer Here" />
<Grid BackgroundColor="White">
<skia:SKCanvasView x:Name="canvasView"
PaintSurface="OnCanvasViewPaintSurface"/>
<Grid.Effects>
<tt:TouchEffect Capture="True"
TouchAction="OnTouchEffectAction" />
</Grid.Effects>
</Grid>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Change your StackLayout to a Grid and specify that Row 2 has a Height of *. That will force Row 2 to consume all extra space.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
xmlns:tt="clr-namespace:TouchTracking"
x:Class="MathKumu.Pages.WorkPage">
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<Grid.RowDefinitions>
<Label Grid.Row="0" Text="{Binding EquationString}" />
<Entry Grid.Row="1" Placeholder="Put Answer Here" />
<Grid Grid.Row="2" BackgroundColor="White">
<skia:SKCanvasView x:Name="canvasView"
PaintSurface="OnCanvasViewPaintSurface"/>
<Grid.Effects>
<tt:TouchEffect Capture="True"
TouchAction="OnTouchEffectAction" />
</Grid.Effects>
</Grid>
</Grid>
</ContentPage.Content>
</ContentPage>
I have a StackLayout which has items dynamically added to it when a user is selected. I want it to have a height of around 200, then if the list is longer than this, it should be scrollable.
If I add a height request to it as it is now, it adjusts the height and the scrollbar works but prevents items being added after the bottom of the box (so the scrollbar is basically pointless.
This is the code, the StackLayout is called 'readout':
<?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="Clocker.MainPage" >
<StackLayout x:Name="mainstack">
<Picker x:Name="locationpicker" SelectedIndexChanged="locationpicker_SelectedIndexChanged" BackgroundColor="#baf4d5"></Picker>
<Label x:Name="timeLabel" FontSize="50" HorizontalTextAlignment="Center" VerticalTextAlignment="Start" TextColor="White" BackgroundColor="#59a092"/>
<ScrollView Orientation="Vertical" BackgroundColor="#baf4d5">
<StackLayout x:Name="readOut">
</StackLayout>
</ScrollView>
<ListView x:Name="userslist" BackgroundColor="#59a092">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="OnIn" CommandParameter="{Binding .}"
Text="In" />
<MenuItem Clicked="OnOut" CommandParameter="{Binding .}"
Text="Out" IsDestructive="True" />
</ViewCell.ContextActions>
<StackLayout Padding="15,0">
<Label x:Name="lblname" Text="{Binding FullName}" TextColor="White" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
I've 2 or 3 pages in my app that are more or less like what you described.
My solution uses and 2 lists.
More or less like this:
<Grid ColumnSpacing="0" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="2*" />
<RowDefinition Height="8*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
Row 1 is where I have my first list, row 2 is where the second list goes.
I do it this way (0 is a header and 3 is a footer), so I have more or less 20% of the left space on top and the rest of the space allocated for the second list.
Hope it's clear.
I have a problem. I created a page that looks like this:
Now I want the content of the CollectionView to be centered. I already tried things to set on HorizontalOptions=Center, but no luck!
Here is the code of that part:
<StackLayout HorizontalOptions="CenterAndExpand">
<CollectionView ItemsSource="{Binding coinDataList}" ItemsLayout="HorizontalList" Margin="0" HorizontalOptions="CenterAndExpand" BackgroundColor="Red">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid RowSpacing="0" Margin="20,0,20,0" HorizontalOptions="CenterAndExpand" Padding="0">
<Grid.RowDefinitions>
<RowDefinition Height="20" />
<RowDefinition Height="5" />
<RowDefinition Height="20" />
<RowDefinition Height="10" />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Label Grid.Row="0" VerticalOptions="CenterAndExpand" HorizontalOptions="Center" Text="{Binding Coin}" FontAttributes="Bold" TextColor="#00D8FF" FontSize="18"/>
<Label Grid.Row="2" VerticalOptions="CenterAndExpand" HorizontalOptions="Center" Text="{Binding Price, StringFormat='{0:F2}'}" TextColor="White" FontSize="18"/>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
How can I do that?
You can achieve this by using BindableLayout in conjunction with the StackLayout with horizontal orientation. This will not be as performant as CollectionView, but from your UI, it looks like you will not be having a lot of items in your ItemSource collection, but you your need UI to be dynamic and evenly spaced and centered when there are fewer items. As the item list grows, the UI will look more like the horizontal list view.
So here is the minimal working XAML which you can modify to fit into your project. For sake of simplicity, I have added everything in the XAML (no code behind), so you can plug this XAML right into the content page and test it out!
<?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:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:generic="clr-namespace:System.Collections.Generic;assembly=netstandard"
mc:Ignorable="d"
x:Class="Playground.MainPage">
<ContentPage.Resources>
<ResourceDictionary>
<generic:List x:Key="SymbolNames" x:TypeArguments="x:String">
<x:String>BTC</x:String>
<x:String>LTC</x:String>
<x:String>ETH</x:String>
<x:String>OT1</x:String>
<x:String>OT2</x:String>
<x:String>OT3</x:String>
<x:String>OT4</x:String>
<x:String>OT5</x:String>
<x:String>OT6</x:String>
</generic:List>
</ResourceDictionary>
</ContentPage.Resources>
<ScrollView Orientation="Horizontal" HeightRequest="60" VerticalOptions="Start">
<StackLayout BindableLayout.ItemsSource="{Binding Source={StaticResource SymbolNames}}" Orientation="Horizontal">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label Text="{Binding}" HorizontalOptions="CenterAndExpand" VerticalOptions="Center" Margin="10"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
</ScrollView>
</ContentPage>
UI when 3 Items:
UI When multiple overflowing items: