英文:
.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).
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
我做了一些更改:
- 我尝试以MVVM方式使用数据绑定。
- 我尝试使用平台代码计算图像比率。
以下是我的代码,
对于 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:
- I tried using data binding in MVVM way.
- 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.
<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>
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("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();
}
}
}
}
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 = "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;
}
}
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 > 0 && AspectRatio > 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
<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>
Hope it works for you.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论