Xamarin.Forms: adjust Image size to the width of the parent's in a BindableLayout

833 views Asked by At

I'm trying to adjust the the Image size to the width of the parent's container in a BindableLayout, but I didn't found a way to achieve this.

I'm based on this other topic to achieve this.

I first tried to embed the Image in a Grid container like this:

<StackLayout x:Name="NewsList"
             BindableLayout.ItemsSource="{Binding News}">
    <BindableLayout.ItemTemplate>
        <DataTemplate>
            <Frame>
                <Grid Padding="0" Margin="0"
                      VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
                      BackgroundColor="Red">
                    <Image Source="{Binding Image}" Aspect="AspectFit"/>
                </Grid>
                <Label Text="Description" />
            </Frame>
        </DataTemplate>
    </BindableLayout>
</StackLayout

=> but we can see that I get red stripes around the images (at the top/bottom, or at the left/right): ImageInGrid

Then, I've tried to use a CachedImage from FFImageLoading like this:

<Grid Padding="0" Margin="0"
        HorizontalOptions="FillAndExpand"
        VerticalOptions="FillAndExpand"
        BackgroundColor="Orange">
    <ffimageloading:CachedImage Source="{Binding Image}"
                    HorizontalOptions="Fill"
                    VerticalOptions="Fill"
                    Aspect="AspectFill"
                    DownsampleToViewSize="True"/>
</Grid>

=> but in this case, the images are not fully visible, or are truncated CachedImage

=> So is there another way allowing me to display an image in the full width of the parent's container, and keeping the original ratio?

Update 1:

The displayed images are coming from Facebook posts. Here are the fourth images that are displayed:

  1. https://scontent-cdt1-1.xx.fbcdn.net/v/t1.0-9/s720x720/118713552_3623822074306674_9076571821151026884_n.jpg?_nc_cat=110&_nc_sid=110474&_nc_ohc=8xcbXj0tf5IAX-b_jE9&_nc_ht=scontent-cdt1-1.xx&tp=7&oh=60af4b756944856e28327736fd542c65&oe=5F98D58D
  2. https://scontent-cdg2-1.xx.fbcdn.net/v/t15.13418-10/96415113_248439429597332_6367448024599232512_n.jpg?_nc_cat=100&_nc_sid=ad6a45&_nc_ohc=2jBGHupMA20AX-8Y-M8&_nc_ht=scontent-cdg2-1.xx&oh=918470153ca23c927b921b2f1a61d4a5&oe=5F97D9C7
  3. https://scontent-cdg2-1.xx.fbcdn.net/v/t15.5256-10/95397765_284933452664428_1743250590344937472_n.jpg?_nc_cat=111&_nc_sid=ad6a45&_nc_ohc=LWajKszkHiMAX-sqkeZ&_nc_oc=AQmqjn5ykjy2tYfmRvpQChhtdsJZgk9_Smn3oU9weGt5xe9QY4933u_sNV1qAnZrIFc&_nc_ht=scontent-cdg2-1.xx&oh=c93af2de18eb417b224d8ea211197cda&oe=5F98A096
  4. https://scontent-cdg2-1.xx.fbcdn.net/v/t1.0-9/s720x720/95921743_3263337923688426_3234683279575613440_o.jpg?_nc_cat=102&_nc_sid=8024bb&_nc_ohc=AkRxtEdIyU8AX99QWmR&_nc_ht=scontent-cdg2-1.xx&tp=7&oh=6dc746bd0ea30097aee78f57a6395fb4&oe=5F980B69

Update 2:

I've tried the solution given by @Leo:

<StackLayout Orientation="Vertical" x:DataType="model:News">
    <Image Source="{Binding Image}" Aspect="AspectFill"/>
    <Label Text="Description" />
</StackLayout>

But the result is still not good as the first and fourth images are truncated: truncated image

2

There are 2 answers

5
Leo Zhu On

I download the picture and do like below,you could check it:

<StackLayout x:Name="NewsList" BackgroundColor="Red"
         BindableLayout.ItemsSource="{Binding News}">
     <BindableLayout.ItemTemplate>
            <DataTemplate>
                    <StackLayout Orientation="Vertical">
                        <Image Source="{Binding .}" Aspect="AspectFill"/>
                        <Label Text="Description" />
                    </StackLayout>
                </DataTemplate>
     </BindableLayout.ItemTemplate>
</StackLayout>

the effect like:

enter image description here

0
Gold.strike On

I finally found a solution that worked for me here, it's the solution given by Frankvans:

class ImageFit : Image {
    protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) {
        SizeRequest sizeRequest = base.OnMeasure(double.PositiveInfinity, double.PositiveInfinity);

        var innerRatio = sizeRequest.Request.Width / sizeRequest.Request.Height;

        if (double.IsNaN(innerRatio))
            return sizeRequest;

        // Width needs to be adjusted
        if (double.IsInfinity(heightConstraint)) {
            // Height needs to be adjusted
            if (double.IsInfinity(widthConstraint)) {
                widthConstraint = sizeRequest.Request.Width;
                heightConstraint = sizeRequest.Request.Height;
            } else {
                // Adjust height
                heightConstraint = widthConstraint * sizeRequest.Request.Height / sizeRequest.Request.Width;
            }
        } else if (double.IsInfinity(widthConstraint)) {
            // Adjust width
            widthConstraint = heightConstraint * sizeRequest.Request.Width / sizeRequest.Request.Height;
        } else {
            // strech the image to make it fit while conserving it's ratio
            var outerRatio = widthConstraint / heightConstraint;

            var ratioFactor = (innerRatio >= outerRatio) ?
                (widthConstraint / sizeRequest.Request.Width) :
                (heightConstraint / sizeRequest.Request.Height);

            widthConstraint = sizeRequest.Request.Width * ratioFactor;
            heightConstraint = sizeRequest.Request.Height * ratioFactor;
        }
        sizeRequest = new SizeRequest(new Size(widthConstraint, heightConstraint));
        return sizeRequest;
    }
}