Image Will Not Aspect Fit/Fill While Inside ScrollView - xamarin

I have a Grid with a few Rows defined. Within one of those rows is a single ScrollView. That ScrollView has a Grid with a single Image inside that's used as a sort of BackGround Image for one section. No matter what I do I cannot get the Image to Fill, AspectFill or AspectFit inside the Parent Grid (I have also tried a StackView to no avail). If I eliminate the ScrollView and pull the Grid and Image out the Image will Fit or Fill just fine.
Here is a stripped down example of what I'm doing:
<Grid ColumnSpacing="0" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="48"/>
<RowDefinition Height="4"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0"> ... </Grid>
<Grid Grid.Row="1"> ... </Grid>
<ScrollView Orientation="Vertical" HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" Grid.Row="2">
<Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<!-- THIS IMAGE WILL NOT FILL! -->
<Image Source="{local:EmbeddedImage Project.Mobile.Images.fieldBackground.png}" Aspect="Fill" />
</Grid>
... More Code ...
</ScrollView>
</Grid>
No matter what I do the Image will not Fill the Grid Parent. If I remove the ScrollView it works just fine like this but I cannot do this without a ScrollView because I have more content directly below that cannot fit on the screen.
<Grid ColumnSpacing="0" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="48"/>
<RowDefinition Height="4"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0"> ... </Grid>
<Grid Grid.Row="1"> ... </Grid>
<Grid Grid.Row="2" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<!-- THIS IMAGE FILLS FINE! -->
<Image Source="{local:EmbeddedImage Project.Mobile.Images.fieldBackground.png}" Aspect="Fill" />
</Grid>
</Grid>
As a workaround I attempted to not aspect fit/fill the image but to anchor it at the top of the Grid and let it fill horizontally. But I cannot get the image to fit any other way inside the Grid besides centered vertically no matter what I try. If I make the Grid the exact height of the image it almost works but it looks different between iOS and Android. This seems like such a simple thing? What am I missing? I've wasted hours on this so far.
Thanks,
Any help is appreciated!

I would put the background image outside (below) the scrollview.
If you put both elements inside the same row/column in a grid, they will overlap.
The first child is at the back of the Z stack, the second child is placed above it, and so on.
<Grid ColumnSpacing="0" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="48"/>
<RowDefinition Height="4"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0"> ... </Grid>
<Grid Grid.Row="1"> ... </Grid>
<Image Grid.Row="2" Source="{local:EmbeddedImage Project.Mobile.Images.fieldBackground.png}" Aspect="Fill" />
<ScrollView Orientation="Vertical" HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" Grid.Row="2">
... Insert your elements here ...
</ScrollView>
</Grid>

Related

Xamarin ScrollView inside StackLayout

I have a view with grid which consists of two stacklayouts positioned vertically.
I would like an effect that second stacklayout has scrollview only because I build its content dynamically on page model side. When content of second stacklayout is built then on screen I see only that second stacklayout. I want to see first and second already built with possibility of scrolling. Any ideas ?
<StackLayout VerticalOptions="StartAndExpand" Spacing="0">
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
<ColumnDefinition Width="0.2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<StackLayout Spacing="0" VerticalOptions="StartAndExpand"
Margin="0" Padding="0" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="5">
<Some static content/>
</StackLayout>
<StackLayout Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="5" Spacing="0" Margin="0">
<ScrollView>
<StackLayout x:Name="details">
</StackLayout>
</ScrollView>
</StackLayout>
</Grid>
</StackLayout>
The definition of your Grid rows are wrong. The StackLayout with ScrollView should have * and the other should have Auto Height.
<ScrollView>
<StackLayout x:Name="details">
Layout overflow is required. otherwise, it is not displayed.
Add buttons for example.
</StackLayout>
</ScrollView>

In Xamarin.Forms, how to make image shrink to match container size

I have a Xamarin.Forms app with a page that show an image and some other elements. The image is a png and on some screens it is too large for it to show unscaled while all the other elements also show.
My question is: Is there any way to get Xamarin.Forms to automatically scale the image down in order to fit everything on screen?
I have a small example to show the problem:
<?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:local="clr-namespace:PocImageScaling"
x:Class="PocImageScaling.MainPage">
<StackLayout x:Name="stack1" BackgroundColor="Gray" Spacing="0">
<BoxView x:Name="box1" HeightRequest="200" BackgroundColor="Yellow" />
<Image x:Name="img1" Source="infoscreen_graphic.png" Aspect="AspectFit"/>
<BoxView x:Name="box2" HeightRequest="200" BackgroundColor="Olive" />
<BoxView x:Name="box3" HeightRequest="50" BackgroundColor="Yellow" />
</StackLayout>
</ContentPage>
and in code-behind I have
protected override void OnAppearing()
{
base.OnAppearing();
Debug.WriteLine($"page.Height = {this.Height}");
Debug.WriteLine($"stack1.Height = {stack1.Height}");
Debug.WriteLine($"box1.Height = {box1.Height}");
Debug.WriteLine($"img1.Height = {img1.Height}");
Debug.WriteLine($"box2.Height = {box2.Height}");
Debug.WriteLine($"box3.Y = {box3.Y}, box3.Height = {box3.Height}");
}
What I see on run-time on an iPhone SE is
page.Height = 568
stack1.Height = 568
box1.Height = 200
img1.Height = 152
box2.Height = 200
box3.Y = 552, box3.Height = 50
The yellow box3 is almost not visible at the bottom and thus goes beyond the bounds of the StackLayout and the ContentPage.
I would have liked instead that the Image would shrink enough for everything to be on-screen.
If you want the image to scale and only take up the available space I would switch to a Grid instead of a StackLayout.
<Grid x:Name="grid1" BackgroundColor="Gray" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<BoxView x:Name="box1" HeightRequest="200" BackgroundColor="Yellow" />
<Image Grid.Row="1" x:Name="img1" Source="AppIcon" Aspect="AspectFit" BackgroundColor="Pink"/>
<BoxView Grid.Row="2" x:Name="box2" HeightRequest="200" BackgroundColor="Olive" />
<BoxView Grid.Row="3" x:Name="box3" HeightRequest="50" BackgroundColor="Yellow" />
</Grid>
The <RowDefinition Height="Auto"/> will adjust to your set HeightRequest of the view in that row and the <RowDefinition Height="*"/> will then fill the available space left, which should let everything fit on the screen.

How to use an Image on multiple rows in a Grid properly in Xamarin Forms

I am trying to create a custom, material-style, card cell in my Xamarin Forms app. I have the appearance pretty much down, but I'm having problems with the image in it. I want it to touch the top and bottom edges, the left hand edge, and be a square sort of shape, while maintaining the aspect ratio. But right now, all I get is this small image that won't play ball:
(I've had to cover the company images with paint, but trust me that they're about that size).
Here's what I actually want (again, please excuse the paint job)
I'm using an image in a grid view, in the 1st column and spanning all 4 rows. I've tried all of the LayoutOptions, which I used to understand but now I'm second guessing myself. I've also tried putting the image in a StackLayout as I thought you can expand children of a Stacklayout, but still no dice. Here is my simplified Xaml right now:
<Frame CornerRadius="10"
Margin="10, 5"
IsClippedToBounds="True"
BackgroundColor="White">
<Grid BackgroundColor="White" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackLayout Grid.Row="0" Grid.Column="0" Grid.RowSpan="4"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<Image HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Aspect="AspectFill" Source="{Binding ImageSource}"/>
</StackLayout>
<Label Grid.Row="0" Grid.Column="1"
Text="{Binding Favourite.FavKindName}"
FontSize="{DynamicResource InfoLargerTextFontSize}"/>
<Image Grid.Row="1" Grid.Column="3" Grid.RowSpan="4" Source="Contact.png"
VerticalOptions="CenterAndExpand" >
<Image.GestureRecognizers>
<TapGestureRecognizer />
</Image.GestureRecognizers>
</Image>
</Grid>
</Frame>
What's more, you can probably tell I'm pretty clueless about the phone icon on the right. I want that to occupy the centre and be of a decent button size for the card cell.
I've spent hours trying to figure this out. What am I doing wrong?
Frame has a default Padding of 20. That's why you have those margins inside the frame.
<Frame Padding="0" // Here , set padding to 0, so you can fill all Frame space
CornerRadius="10"
Margin="10, 5"
IsClippedToBounds="True"
BackgroundColor="White">

How can I make the background of a grid fill from top to bottom?

I have a grid area and I would like for that to be filled from top to bottom with the background green color:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="72*" />
<RowDefinition Height="10*" />
</Grid.RowDefinitions>
Here is Row 2
<Grid Grid.Row="2" HorizontalOptions="FillAndExpand" VerticalOptions="Center" BackgroundColor="#EEEEEE">
<Grid Padding="10,10,10,10" VerticalOptions="FillAndExpand"
BackgroundColor="Lime"/>
</Grid>
What I get with this code is a white area that's the correct size of the grid but there's just a small green line in the middle.
How can I make the grid fill completely?
The way to achieve this is to set Background attribute of tag "Grid" to your color of choice.
<Grid x:Name="phraseGrid" BackgroundColor="Green" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Margin="0,20,0,0" RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="72*" />
<RowDefinition Height="10*" />
</Grid.RowDefinitions>
<Grid Grid.Row="2" x:Name="buttonGrid" HorizontalOptions="FillAndExpand" VerticalOptions="Center" BackgroundColor="#EEEEEE">
<Grid IsVisible="{Binding ButtonGridVisible, Converter={StaticResource InverseBoolConverter} }" Padding="10,10,10,10" VerticalOptions="FillAndExpand" BackgroundColor="Lime">
</Grid>
You can create an AbsoluteLayout as a root.
And put your background grid first on the AbsoluteLayout with full width and height.
Then add your content on the same AbsoluteLayout as well.

PerformanceProgressBar only displays one dot

I am using the PerformanceProgressBar from Silverlight toolkit on the (pseudo) splashpage. However, it only displays one moving dot. What is wrong?
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="ActiveSplash" Height="Auto" Width="480" Background="Pink" Grid.Row="1" Visibility="Visible">
<Image Name="SplashScreenImage" Source="/SplashScreenImage.jpg"></Image>
<toolkit:PerformanceProgressBar Width="480" Height="Auto"
IsIndeterminate="True"
Foreground="Blue"
Background="Blue"
Margin="0,104,0,0" />
</Grid>
<Grid x:Name="ContentPanel" Visibility="Collapsed" Grid.Row="2">
<!-- stuff -->
</Grid>
</Grid>
Is your app doing a lot of processing while using the performance progress bar?
I've notices that the more you have in the UI thread, less points you see in the bar.
Try doing your processing in a background thread

Resources