7
votes

I have the following simple XAML page:

<?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="Test.UserGuides.VPN">
    <ContentPage.Content>
        <ScrollView>
            <StackLayout HorizontalOptions="Center" VerticalOptions="Center" Margin="10,10,10,10">
                <Label Margin="10,10,10,10" Text="How to connect to VPN." HorizontalOptions="Center" />
                <Label Margin="10,10,10,10" Text="If you have a corporate notebook, look for the Cisco AnyConnect application. Either in your start menu, on your desktop, or in your taskbar." />
                <Image x:Name="imgVPN1" Margin="10,10,10,10" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
                <Label Margin="10,10,10,10" Text="Select your region and press the Connect button." />
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>
</ContentPage>

In the constructor, I call a method to load the images:

private void LoadImages()
{
    imgVPN1.Aspect = Aspect.AspectFit;
    ImageSource imagesrc = ImageSource.FromResource("Test.Files.CiscoAnyConnect.PNG");
    imgVPN1.Source = imagesrc;
}

The result looks like this on my (rather large, high DPI) phone:

imgur link 1

Of course, I want the image to automatically expand so it takes up the entire width of the screen. While maintaining the aspect ratio. But how can I achieve this? I've already tried putting the Aspect to "AspectFill", and added

imgVPN1.WidthRequest = Application.Current.MainPage.Width;

To the LoadImages method, but that makes the end result look like this:

imgur link 2

I've been toying around with various HorizontalOptions, VerticalOptions, Aspects, GridView, StackLayouts,... The end result is always either the first or the second screenshot. So how can I achieve what I want here?

2
what is your image size to experiment?Yuri S
@YuriS The dimension of the CiscoAnyConnect.PNG image is 411x 191. If I could get those values it would be easy to set the HeightRequest to the aspect ratio, but it seems to be near impossible to do that with Xamarin.Forms from my research the past hours.Matthias
can you post it somewhere so I don't need to rectreate similar?Yuri S
Sure thing: imgur.com/Z487WqBMatthias
There are 2 bugs created. One for grid and one for StackLayout. Bugs confirmed but not fixed. I would try to use relative layout if you need to scale a picture. Sorry bugzilla.xamarin.com/show_bug.cgi?id=27729 and bugzilla.xamarin.com/show_bug.cgi?id=55294Yuri S

2 Answers

11
votes

Here is what can be done. XML almost didn't change, I just removed image Layout Options

<ContentPage.Content>
        <ScrollView>
            <StackLayout HorizontalOptions="Center" VerticalOptions="Center" Margin="10,10,10,10">
                <Label Margin="10,10,10,10" Text="How to connect to VPN." HorizontalOptions="Center" />
                <Label Margin="10,10,10,10" Text="If you have a corporate notebook, look for the Cisco AnyConnect application. Either in your start menu, on your desktop, or in your taskbar." />
                <Image x:Name="imgVPN1" Margin="10,10,10,10" />
                <Label Margin="10,10,10,10" Text="Select your region and press the Connect button." />
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>

After implementing everything in relative layout which also was not simple (I have the code if anybody needs it let me know) I found easier way. The key point is that image doesn't scale correctly and occupies too much space in height. But we know the size ratio of this image so we can use it. In the code we need to override OnSizeAllocated because in constructor the width is unknown yet. Then it's easy

protected override void OnSizeAllocated(double width, double height)
{
    base.OnSizeAllocated(width, height);
    imgVPN1.WidthRequest = width;
    imgVPN1.HeightRequest = width / 2.152; //given that image is 411 x 191
}

You could use other width than page with if you want. For example you could use stack layout width to consider margins for more accuracy but this is already tuning. Or you actually could use the image width itself like that

 protected override void OnSizeAllocated(double width, double height)
 {
     base.OnSizeAllocated(width, height);
     double needHeight=imgVPN1.Width / 2.152;
     if (imgVPN1.Height != needHeight)
         imgVPN1.HeightRequest = needHeight;
 }

enter image description here

-1
votes

Here is what you need.

<ContentPage.Content>
    <ScrollView>
        <StackLayout Margin="20" Spacing="10">
            <Label Text="How to connect to VPN." HorizontalOptions="Center" />
            <Label Text="If you have a corporate notebook, look for the Cisco AnyConnect application. Either in your start menu, on your desktop, or in your taskbar." />
            <Image Source="yourimage.jpg" HorizontalOptions="Fill" />
            <Label Text="Select your region and press the Connect button." />
        </StackLayout>
    </ScrollView>
</ContentPage.Content>