Xamarin形成具有100%父容器宽度和自动高度以保持纵横比的图像

时间:2020-03-11 11:50:33

标签: xaml xamarin xamarin.forms

Image是否有可能占据其父容器的100%宽度,而实际上将整个图像放置在该容器中而不进行裁剪,同时又自动调整了高度以保留纵横比?

我在SO和Xamarin论坛上都读过类似的问题,但是显然,如果不实现自定义渲染器或手动计算代码中的正确大小,就无法做到这一点。但是要在代码中进行计算,您将需要图像尺寸或纵横比。对于那些都不为人所知的应用,这是一个问题。

就CSS而言,我正在寻找的解决方案类似于

width:100%; height:auto;

在我看来,为这样一个琐碎的任务实现定制渲染器是一个过大的选择,对Xamarin来说是一个巨大的尴尬;除非我理解不对。

4 个答案:

答案 0 :(得分:2)

我无法找到用于此问题的纯XAML解决方案,因此决定使用ffimageloadingSuccess事件来查找加载图像的原始宽度和高度,并从中获取长宽比值,将其存储并在SizeAllocated事件中使用它,以确保图像的宽高比,同时确保其宽度为父容器的100%。

示例代码:

    private void testImage_OnSuccess(object sender, CachedImageEvents.SuccessEventArgs e)
    {
        var image = sender as CachedImage;
        double width = e.ImageInformation.OriginalWidth;
        double height = e.ImageInformation.OriginalHeight;

        ratio = width / height; // store it in a variable

    }


    protected override void OnSizeAllocated(double width, double height)
    {
        base.OnSizeAllocated(width, height);

        if (this.Width > 0 && ratio != 0) // width of the parent container
            testImage.HeightRequest = this.Width / ratio;
    }

答案 1 :(得分:1)

将图像放置在框架中。然后根据框架设置图像的高度和宽度。

 <Frame>
        <Image></Image>
    </Frame>

您可以通过绑定值转换器根据您的框架更改宽度和高度。

绑定值转换器:https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/converters

首先将名称设置为您的相框。

<Frame
…………
x:Name="frame"/>

创建MyConverter。您可以在Convert方法中更改值的百分比。 MyConverter.cs

public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    return (double)value;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    throw new NotImplementedException();
}
}

设置StaticResource。

<ContentPage.Resources>
<ResourceDictionary>
    <local:MyConverter x:Key="MyConverter" />
</ResourceDictionary>

绑定到您的图片。

 <Image WidthRequest="{Binding Source={x:Reference frame},Path=Width,Converter={StaticResource MyConverter}}"
                    HeightRequest="{Binding Source={x:Reference frame},Path=Height,Converter={StaticResource MyConverter}}"></Image>

答案 2 :(得分:1)

我一直在寻找这个问题的答案。正如其他人指出的那样,我没有找到仅Xaml的解决方案。我选择了一条不同的路线,并将解决方案提供给那些可能会很有启发性的人,并为更改FFImageLoading以正确解决此问题提供了种子。

我创建了CachedImage的子类并覆盖了OnMeasure。为了使CachedImage.OnMeasure在宽高比模式(而非填充模式)下工作,它必须返回与基础图像的比率匹配的SizeRequest。因此,我选择的解决方案只是使用提供的widthConstraint并将高度计算为widthConstraint / ratio。本描述仅解决以下多种情况之一:widthConstraint不是无限,并且希望回答此处提出的特定问题(宽度100%和自动高度)。

实现这种情况的子类:

public class CachedImage2 : CachedImage
{
    protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
    {
        var sr = base.OnMeasure(widthConstraint, heightConstraint);
        if (sr.Request.IsZero)
            return sr;

        var ratioWH = sr.Request.Width / sr.Request.Height;
        var sr2 = new SizeRequest(new Size(widthConstraint, widthConstraint / ratioWH));
        return sr2;
    }
}

答案 3 :(得分:0)

假设您说:

并自动调整高度。

您的意思是容器的高度。 是的,这完全可以在Xamarin.Forms中实现。

假设我有一个Grid作为父容器。这就是我的做法。

 <!-- remove all the padding & margin & spacing on Grid -->
<Grid RowSpacing="0"
      ColumnSpacing="0"
      Margin="0"
      Padding="0">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" /> <!-- the containers height will now adjust --> 
        <RowDefinition Height="56"/> <!-- This one is for the other content in your view etc -->
    </Grid.RowDefinitions>
    <!-- Put your image inside your parent container and apply properties -->
    <Image Source="some_source.png"
           HorizontalOptions="FillAndExpand"
           VerticalOptions="FillAndExpand"/>
</Grid>

水平和垂直选项就像在CSS中设置width:100%和height:100%一样。