.NET MAUI图像大小错误

huangapple go评论58阅读模式
英文:

.NET MAUI Image wrong size

问题

我在.NET MAUI上显示图像时遇到了一个问题,图像的大小总是比实际大小要大(图像下方的蓝色部分)。

我的代码如下:

<Grid>
    <ScrollView>
        <VerticalStackLayout>
            <Image Source="https://cdn-5e5150f5f911c807c41ebdc8.closte.com/wp-content/uploads/IoT-development-kit-article-banner-scaled-900x400.jpg"
                    Aspect="AspectFit" BackgroundColor="Blue">
                <Image.Margin>
                    <OnIdiom Phone="10" Tablet="20" Desktop="20"/>
                </Image.Margin>
            </Image>
        </VerticalStackLayout>
    </ScrollView>
</Grid>

有办法保持图像的大小与实际大小成比例吗?

英文:

I'm having a problem when I show an image on .NET MAUI, the size of the image is always bigger than it actually is (blue part in the image below).

.NET MAUI图像大小错误

My code is as follows:

<Grid>
    <ScrollView>
        <VerticalStackLayout>
            <Image Source="https://cdn-5e5150f5f911c807c41ebdc8.closte.com/wp-content/uploads/IoT-development-kit-article-banner-scaled-900x400.jpg"
                    Aspect="AspectFit" BackgroundColor="Blue">
                <Image.Margin>
                    <OnIdiom Phone="10" Tablet="20" Desktop="20"/>
                </Image.Margin>
            </Image>
        </VerticalStackLayout>
    </ScrollView>
</Grid>

Is there a way to keep the size of the image in proportion to the actual size?

答案1

得分: 1

我做了一些更改:

  1. 我尝试以MVVM方式使用数据绑定。
  2. 我尝试使用平台代码计算图像比率。

以下是我的代码,

对于 MainPage.xaml,不同之处在于我使用数据绑定来绑定图像的 Source 和 AspectRatio 属性,这些属性将在 MainPageViewModel 中声明。

<Grid>
    <ScrollView>
        <VerticalStackLayout>                          
            <a:AspectImage Source="{Binding ImageUrl}"
                     AspectRatio="{Binding AspectRatio}" Aspect="AspectFit" BackgroundColor="Blue">
                <a:AspectImage.Margin>
                    <OnIdiom Phone="10" Tablet="20" Desktop="20"/>
                </a:AspectImage.Margin>
            </a:AspectImage>
        </VerticalStackLayout>
    </ScrollView>
</Grid>

对于自定义控件 AspectImage,不同之处在于我将 AspectRatio 更改为可绑定属性,因为我们要对此属性使用绑定。更多信息请参阅可绑定属性

public class AspectImage : Image
{
    public static readonly BindableProperty AspectRatioProperty = BindableProperty.Create("AspectRatio", typeof(double), typeof(AspectRatioContainer), null);

    public double AspectRatio
    {
        get { return (double)GetValue(AspectRatioProperty); }
        set { SetValue(AspectRatioProperty, value); }
    }

    public AspectImage()
    {
        SizeChanged += HandleSizeChanged;
    }

    private void HandleSizeChanged(object sender, EventArgs e)
   {
        if (this.Width > 0 && AspectRatio > 0)
        {
            var desiredHeightRequest = this.Width * AspectRatio;
            if ((int)desiredHeightRequest != (int)HeightRequest)
            {
                this.HeightRequest = (int)desiredHeightRequest;
                InvalidateMeasure();
            }
        }
    }
}

对于 MainPageViewModel,我们为自定义控件添加了 AspectRatio 和 ImageUrl 属性,并计算了 AspectRatio。

public class MainPageViewModel
{
    public string ImageUrl { get; set; }
    public double AspectRatio { get; set; }

    public MainPageViewModel()
    {
        ImageUrl = "https://cdn-5e5150f5f911c807c41ebdc8.closte.com/wp-content/uploads/IoT-development-kit-article-banner-scaled-900x400.jpg";
        AspectRatio = CountAspectRatio(ImageUrl);
    }

    private double CountAspectRatio(string imageUrl)
    {
        var service = new GetImageSizeService();
        Size imageSize = service.GetImageSize(imageUrl);
        return imageSize.Height / imageSize.Width;
    }
}

从上述 MainPageViewModel 中的代码,我们通过调用平台代码来计算 AspectRatio。如果您对此不熟悉,我建议您首先查看这个教程:如何在.NET MAUI中编写特定于平台的代码

在.NET MAUI中注入平台代码(在 Xamarin 中可以使用 DependencyService):

首先,在项目文件夹中,创建一个新的局部类,我们称之为 GetImageSizeService:

public partial class GetImageSizeService
{
    public partial Size GetImageSize(string file);
}

然后,在 Platforms/iOS 文件夹中创建另一个局部类,也叫 GetImageSizeService。注意命名空间应该与上述文件相同

public partial class GetImageSizeService
{
    public partial Size GetImageSize(string file)
    {
        NSData data = NSData.FromUrl(NSUrl.FromString(file));
        UIImage image = UIImage.LoadFromData(data);
        return new Size((double)image.Size.Width, (double)image.Size.Height);
    }
}

然后在 MainPageViewModel 中,我们只需调用此服务并计算 AspectRatio。

=========================== 第一篇帖子 =============

你添加的链接给了我灵感。如果我理解你的问题正确,你可以尝试以下代码,这对我有效:

创建一个名为 AspectImage 的自定义控件,为宽度和高度设置纵横比。

public class AspectImage : Image
{
    public double AspectRatio { get; set; }

    public AspectImage()
    {
        SizeChanged += HandleSizeChanged;
    }

    private void HandleSizeChanged(object sender, EventArgs e)
    {
        if (this.Width > 0 && AspectRatio > 0)
        {
            var desiredHeightRequest = this.Width * AspectRatio;           
            if ((int)desiredHeightRequest != (int)HeightRequest)
            {
                this.HeightRequest = (int)desiredHeightRequest;
                InvalidateMeasure();
            }
        }
    }
}

对于 xaml,使用 AspectImage。这里的纵横比似乎是 4/9,大约等于 0.44。

<Grid>
    <ScrollView>
        <VerticalStackLayout>                          
            <a:AspectImage Source="https://cdn-5e5150f5f911c807c41ebdc8.closte.com/wp-content/uploads/IoT-development-kit-article-banner-scaled-900x400.jpg"
                     AspectRatio="0.44" Aspect="AspectFit" BackgroundColor="Blue">
                <a:AspectImage.Margin>
                    <OnIdiom Phone="10" Tablet="20" Desktop="20"/>
                </a:AspectImage.Margin>
            </a:AspectImage>
        </VerticalStackLayout>
    </ScrollView>
</Grid>

希望对你有帮助。

英文:

I made some changes:

  1. I tried using data binding in MVVM way.
  2. I tried counting image ratio using platform code.

The following is my code,

For MainPage.xaml, the difference is that i use data binding for image Source and AspectRatio property which would be claimed in MainPageVeiwModel.

&lt;Grid&gt;
    &lt;ScrollView&gt;
        &lt;VerticalStackLayout&gt;                          
            &lt;a:AspectImage Source=&quot;{Binding ImageUrl}&quot;
                     AspectRatio=&quot;{Binding AspectRatio}&quot; Aspect=&quot;AspectFit&quot; BackgroundColor=&quot;Blue&quot;&gt;
                &lt;a:AspectImage.Margin&gt;
                    &lt;OnIdiom Phone=&quot;10&quot; Tablet=&quot;20&quot; Desktop=&quot;20&quot;/&gt;
                &lt;/a:AspectImage.Margin&gt;
            &lt;/a:AspectImage&gt;
        &lt;/VerticalStackLayout&gt;
    &lt;/ScrollView&gt;
&lt;/Grid&gt;

For custom control AspectImage, the difference is that I changed AspectRatio to Bindable property as we use binding for this property. More info Bindable properties.

public class AspectImage : Image
{
    public static readonly BindableProperty AspectRatioProperty = BindableProperty.Create(&quot;AspectRatio&quot;, typeof(double), typeof(AspectRatioContainer), null);

    public double AspectRatio
    {
        get { return (double)GetValue(AspectRatioProperty); }
        set { SetValue(AspectRatioProperty, value); }
    }

    public AspectImage()
    {
        SizeChanged += HandleSizeChanged;
    }

    private void HandleSizeChanged(object sender, EventArgs e)
    {
        if (this.Width &gt; 0 &amp;&amp; AspectRatio &gt; 0)
        {
            var desiredHeightRequest = this.Width * AspectRatio;
            if ((int)desiredHeightRequest != (int)HeightRequest)
            {
                this.HeightRequest = (int)desiredHeightRequest;
                InvalidateMeasure();
            }
        }
    }
}

For MainPageViewModel, we add AspectRatio and ImageUrl property for custom control and count AspectRatio.

public class MainPageViewModel
{
	public string ImageUrl { get; set; }
	public double AspectRatio { get; set; }

	public MainPageViewModel()
	{
		ImageUrl = &quot;https://cdn-5e5150f5f911c807c41ebdc8.closte.com/wp-content/uploads/IoT-development-kit-article-banner-scaled-900x400.jpg&quot;;

		AspectRatio = CountAspectRatio(ImageUrl);
    }

    private double CountAspectRatio(string imageUrl)
    {
        var service = new GetImageSizeService();
		Size imageSize = service.GetImageSize(imageUrl);
		return imageSize.Height / imageSize.Width;
    }
}

From above code in MainPageViewModel, we count AspectRatio by call platform code. If you are not familiar with it, i recommend this tutorial first: How To Write Platform-Specific Code in .NET MAUI.

To inject platform code in Maui (in Xamarin could use DependencyService):

First, in Project folder, create a new partial class, let's call it GetImageSizeService:

public partial class GetImageSizeService
{
	public partial Size GetImageSize(string file);
}

Then creat another partial class in Platforms/iOS folder, called it GetImageSizeService also. Pay attention to the namespace should be the same as above file.

public partial class GetImageSizeService
{
    public partial Size GetImageSize(string file)
    {
        NSData data = NSData.FromUrl(NSUrl.FromString(file));

        UIImage image = UIImage.LoadFromData(data);
        return new Size((double)image.Size.Width, (double)image.Size.Height);
    }
}

Then in MainPageViewModel, we just call this service and count the AspectRatio.

=========================== First post=============

The link you add did inspire me. And if i understand your question correctly, you could try the following code which worked for me:

Create AspectImage custom control which set aspect ratio for width and height

public class AspectImage : Image
{
    public double AspectRatio { get; set; }

    public AspectImage()
    {
        SizeChanged += HandleSizeChanged;
    }

    private void HandleSizeChanged(object sender, EventArgs e)
    {
        if (this.Width &gt; 0 &amp;&amp; AspectRatio &gt; 0)
        {
            var desiredHeightRequest = this.Width * AspectRatio;           
            if ((int)desiredHeightRequest != (int)HeightRequest)
            {
                this.HeightRequest = (int)desiredHeightRequest;
                InvalidateMeasure();
            }
        }
    }
}

For xaml, consume the AspectImage. Here the aspect ratio seems to be 4/9 Approximately equal to 0.44

&lt;Grid&gt;
    &lt;ScrollView&gt;
        &lt;VerticalStackLayout&gt;                          
            &lt;a:AspectImage Source=&quot;https://cdn-5e5150f5f911c807c41ebdc8.closte.com/wp-content/uploads/IoT-development-kit-article-banner-scaled-900x400.jpg&quot;
                     AspectRatio=&quot;0.44&quot; Aspect=&quot;AspectFit&quot; BackgroundColor=&quot;Blue&quot;&gt;
                &lt;a:AspectImage.Margin&gt;
                    &lt;OnIdiom Phone=&quot;10&quot; Tablet=&quot;20&quot; Desktop=&quot;20&quot;/&gt;
                &lt;/a:AspectImage.Margin&gt;
            &lt;/a:AspectImage&gt;
        &lt;/VerticalStackLayout&gt;
    &lt;/ScrollView&gt;
&lt;/Grid&gt;

Hope it works for you.

huangapple
  • 本文由 发表于 2023年2月16日 17:55:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75470529.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定