Xamarin Forms 调整图像宽度以填充堆栈布局而无需顶部和底部剪裁

Xamarin Forms Resize image width to fill stacklayout without top and bottom clipping

这是我当前的代码:

<?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);

这是图片:

这是结果:

图像按预期水平填充。

问题是,图像被垂直裁剪。如何防止图像被裁剪以及如何在不拉伸的情况下显示完整图像?


如下面的答案所示,为了调整图像大小,使宽度与 StackLayout 容器的最大宽度匹配而不进行裁剪,我需要设置图像的 HeightRequest。

我正在从 WordPress 网站检索 posts。为了解析来自 Wordpress REST API 的 JSON 响应,我使用了 WordpressPCL 包。为了解析我从 WordpressPCL get post content by ID 方法获得的 HTML 输出,我使用了 HTML Agility Pack。

使用 HTML Agility Pack,我能够获取 Wordpress 媒体 ID,然后使用此 ID 查询 Wordpress API 并获取原始图像的宽度和高度以及标题文本使用 WordpressPCL 包。

根据图片的尺寸,我计算出了纵横比。使用纵横比,我可以通过将纵横比乘以屏幕的总宽度减去 20 来计算图像的新高度。20 是 StackLayout 的左边距 + 右边距,即 parent的图像。

所有图像现在都是全宽以适应 parent 容器的宽度,并且没有被剪裁(100% 高度)。

代码如下(不包括负责解析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);

这是输出:

试试这个。它按预期对我有用。

<?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>

背后的代码:

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);

        }
    }

我的三星A30S的输出