2

This is the current code I have:

<?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="WPapp.Views.Post">
    <ContentPage.Content>
        <ScrollView>
            <StackLayout Margin="10"
                         HorizontalOptions="Center"
                         VerticalOptions="FillAndExpand"
                         x:Name="PostContainer">
                <Image x:Name="FeaturedImage"
                       HorizontalOptions="Center"/>
                <Label x:Name="Title"
                       FontSize="Title"
                       FontAttributes="Bold"
                       Margin="0, 20, 0, 10"/>
                <Label x:Name="PostMeta"
                       FontSize="Caption"
                       FontAttributes="None"
                       Margin="0, 0, 0, 0"/>
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>
</ContentPage>

Image image = new Image();
image.Source = imageSource;
image.Aspect = Aspect.AspectFill;
PostContainer.Children.Add(image);

This is the image:

Image

This is the result:

Result

The image is being filled horizontally as intended.

The problem is, the image is being clipped vertically. How can I prevent the image from being clipped and how do I display the full image without stretching?


As shown in the answer below, in order to resize the image so the width matches the maximum width of the StackLayout Container without clipping, I needed to set the HeightRequest of the image.

I am retrieving posts from a WordPress Website. To parse the JSON response from the Wordpress REST API, I am using the WordpressPCL package. In order to parse the HTML output that I get from the WordpressPCL get post content by ID method, I am using the HTML Agility Pack.

With the HTML Agility Pack, I was able to get the Wordpress media ID, this ID was then used to query the Wordpress API and get the original image's width and height and caption text with the WordpressPCL package.

From the dimensions of the image, I calculated the aspect ratio. With the aspect ratio, I was able to calculate the new Height of the image by multiplying the aspect ratio with the total width of the screen minus 20. 20 is the left margin + right margin of the StackLayout which is the parent of the image.

All the images are now full width to fit the width of the parent container and are not clipped (100% height).

Code is as below (excluding the code which is responsible for parsing the rest of the content of the Wordpress post):

Uri imageSource = new Uri(figure.GetAttributeValue("src", "").ToString());
Int32.TryParse(figure.GetAttributeValue("data-attachment-id", "").ToString(), out int mediaID);
string caption = null;
double aspectRatio = 0;
Task.Run(() =>
{
    Constants wpsite = new Constants();
    var client = new WordPressClient(wpsite.resturl);
    var caption_task = client.Media.GetByID(mediaID);
    caption_task.Wait();
    caption = caption_task.Result.Caption.Rendered;
    double height = caption_task.Result.MediaDetails.Height;
    double width = caption_task.Result.MediaDetails.Width;
    aspectRatio = height / width;
    var htmlCaption = new HtmlDocument();
    htmlCaption.LoadHtml(caption);
    caption = WebUtility.HtmlDecode(htmlCaption.DocumentNode.InnerText);
}).Wait();

Image image = new Image();
image.Source = imageSource;
image.Aspect = Aspect.AspectFit;
double maxWidth = Application.Current.MainPage.Width - 20;
double imageHeight = aspectRatio * maxWidth;
image.HeightRequest = imageHeight;

Label imageCaption = new Label();
imageCaption.Text = caption;
imageCaption.HorizontalTextAlignment = TextAlignment.Center;
imageCaption.FontSize = 12;
imageCaption.Margin = new Thickness(0, 0, 0, 10);

PostContainer.Children.Add(image);
PostContainer.Children.Add(imageCaption);

This is the output:

Output

SidS
  • 306
  • 4
  • 17
  • 1
    you need to set a HeightRequest value on the image – Jason Jun 18 '20 at 19:54
  • image.source is set to the Uri of this image and it is being downsized so the image width matches the width of the StackLayout container. The problem is, the image is clipped vertically. What should I set the HeightRequest to? Please elaborate. – SidS Jun 18 '20 at 19:58
  • the actual height of the image – Jason Jun 18 '20 at 20:01
  • but wouldn't the actual height of the original image be bigger? It's being downsized so the width matches the width of the PostContainer. Wouldn’t this stretch the image vertically? – SidS Jun 18 '20 at 20:02
  • then calculate the appropriate scaled height. You might also try setting the vertical layout options on the image container – Jason Jun 18 '20 at 20:06
  • Something else in your UI is stopping the image from filling. You could try adding `image.VerticalOptions="FillAndExpand"` or `CenterAndExpand`. What control is the StackPanel inside of, I see from the screen shot you have other images and text on the same page. Are all these in the same Stackpanel? – Dizzy Jun 18 '20 at 20:40
  • @Dizzy, yes all the other images and Labels are in the same StackLayout named PostContainer – SidS Jun 18 '20 at 20:42
  • @Jason calculating the scaled height is an option I have in mind. However, I was wondering if Xamarin Forms did that for me, it would save some time – SidS Jun 18 '20 at 20:45
  • @DIzzy FillAndExpand or CenterAndExpand doesn't change anything - all images are still clipped – SidS Jun 18 '20 at 20:52
  • I suspect that since you are loading an image from a URL, that Forms does not have enough information to properly calculate the dimensions when it is laying out the page. Providing a HeightRequest value will provide it with more info. There might be other options, but that's the first thing I'd try – Jason Jun 18 '20 at 20:57
  • @SidS that's odd, that really should do it. Can you try adding the image in the Xaml instead of code behind, any difference? failing that a clean and rebuild. – Dizzy Jun 18 '20 at 20:59
  • Are you experiencing this issue on Android or iOS ? – Adlorem Jun 18 '20 at 21:18
  • @Dizzy I added the image through Xaml, the image was still being clipped. I even tried a clean and build, no difference. – SidS Jun 18 '20 at 21:20
  • @Adlorem I am experiencing this issue on both Android and iOS – SidS Jun 18 '20 at 21:22
  • Post more xaml please. – Adlorem Jun 18 '20 at 21:23
  • I've added the entire XAML file on the question – SidS Jun 18 '20 at 21:26
  • @SidS Hi , have you solved this ? If answer be helpful , remember to mark that when you have time :-) – Junior Jiang Jun 19 '20 at 05:35
  • @SidS it looks like Xamarin.Forms doesn't handle scaling images very well they give us the Aspect property but it's very limited. You can use AspectFit, but this will make the image smaller to fit on screen. The quickest solution would be to do what Jason first commented with setting the Height Request. Alternatively other options are calculate the Height Request in code behind, use a plugin to scale it or use a custom Renderer. – Dizzy Jun 19 '20 at 09:53
  • @Jason setting HeightRequest did the trick! Shame that Xamarin.Forms doesn't do this automatically without clipping the image – SidS Jun 19 '20 at 14:14
  • like I said, I think it's a side effect of needing to calculate the layout before the image is fully downloaded. It could refresh the layout when the image download is complete, like HTML does, but that would be visually jarring. – Jason Jun 19 '20 at 14:16

1 Answers1

0

Try this one. It worked for me as intended.

<?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="PGCubes.Main.Posts">
    <ScrollView>
        <StackLayout Margin="10"
                         HorizontalOptions="Center"
                         VerticalOptions="FillAndExpand"
                         x:Name="PostContainer">
            <Image x:Name="FeaturedImage"
                       HorizontalOptions="Center"/>
            <Label x:Name="Title"
                       FontSize="Title"
                       FontAttributes="Bold"
                       Margin="0, 20, 0, 10"/>
            <Label x:Name="PostMeta"
                       FontSize="Caption"
                       FontAttributes="None"
                       Margin="0, 0, 0, 0"/>
        </StackLayout>
    </ScrollView>
</ContentPage>

The code behind:

public partial class Posts : ContentPage
    {
        public Posts()
        {
            InitializeComponent();


            Title.Text = "Aims of this Mission";
            PostMeta.Text = "Lorem Ipsum is simply dummy text of " +
                "the printing and typesetting industry. Lorem Ipsum has been " +
                "the industry's standard dummy text ever since the 1500s, when " +
                "an unknown printer took a galley of type and scrambled it to " +
                "make a type specimen book. It has survived not only five centuries" +
                ", but also the leap into electronic typesetting, remaining essentially " +
                "unchanged. It was popularised in the 1960s with the release of Letraset " +
                "sheets containing Lorem Ipsum passages, and more recently with desktop " +
                "publishing software like Aldus PageMaker including versions of Lorem Ipsum.";

            Image image = new Image();
            image.HeightRequest = 640;
            image.Source = "https://i.stack.imgur.com/r5pdVl.png";
            image.Aspect = Aspect.AspectFit;
            PostContainer.Children.Add(image);

        }
    }

The output from my samsung A30S enter image description here

Thameem
  • 700
  • 1
  • 13
  • 38
  • This only works for 1 image, but can work for all the images. This can be done by getting the dimensions of each image and setting heightrequest to each images' heights. How can I get the dimensions of an Image from a Url? – SidS Jun 19 '20 at 09:47
  • I believe this link will be helpful to you ... https://stackoverflow.com/questions/30054517/get-image-dimensions-directly-from-url-in-c-sharp – Thameem Jun 19 '20 at 09:54
  • Unfortunately, System.Drawing.Image is not supported in Xamarin.Forms, is there another way to get height from image Url? – SidS Jun 19 '20 at 10:13
  • 1
    I managed to make this work, I had to calculate the aspect ratio using the dimensions of each image by fetching it from the server. Then calculated the HeightRequest using the calculated aspect ratio and the width which is, Application.Current.MainPage.Width - (PostContainerMarginLeft + PostContainerMarginRight ) – SidS Jun 19 '20 at 12:23
  • glad to hear that. It will be helpful if you post the code.. – Thameem Jun 19 '20 at 12:51
  • I have posted the full code with a description in the original question. Thank you very much! – SidS Jun 19 '20 at 14:09