Nicolai Henriksen
Nicolai Henriksen

Reputation: 1504

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.

Upvotes: 0

Views: 508

Answers (1)

Nick Peppers
Nick Peppers

Reputation: 3251

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.

Upvotes: 3

Related Questions