У меня возникла проблема, когда я показываю изображение в .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>
Есть ли способ сохранить размер изображения пропорциональным реальному размеру?
Пожалуйста, прочитайте документы на Aspect
Обратите внимание, что проблема здесь в том, что изображению дается больше места по вертикали, чем ему нужно. Это похоже на layout
проблему, а не Aspect
проблему. Я не понимаю, почему VerticalStackLayout может придать изображению большую высоту, чем необходимо. Предложения для ОП? @copang, это все еще происходит, если удалить ScrollView
? (Я понимаю, что вам может понадобиться ScrollView, но это ценный тест для определения причины.)
Вы можете попробовать установить запрос ширины или высоты для изображения.
@ToolmakerSteve, я пытался удалить ScrollView и даже StackLayout, но результат тот же
@LiqunShen-MSFT, я стараюсь не задавать ширину и высоту, потому что ищу способ, чтобы представление автоматически вычисляло размер. Раньше я использовал решение здесь social.msdn.microsoft.com/Forums/en-US/…, но оно не работает с .NET MAUI
Я внес некоторые изменения:
Ниже приведен мой код,
Для MainPage.xaml разница в том, что я использую привязку данных для свойства Source и AspectRatio изображения, которое будет заявлено в 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>
Для пользовательского элемента управления AspectImage разница в том, что я изменил свойство AspectRatio на Bindable, поскольку мы используем привязку для этого свойства. Подробнее Привязываемые свойства.
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.
Чтобы внедрить код платформы в Maui (в Xamarin можно использовать DependencyService):
Во-первых, в папке Project создайте новый разделяемый класс, назовем его 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>
Надеюсь, это сработает для вас.
Можно ли запросить у источника изображения его ширину и высоту? Избавится от необходимости вручную устанавливать соотношение сторон.
Он работает именно так, как я ожидал, большое спасибо. И, как сказал @ToolmakerSteve, было бы здорово, если бы он мог сам определять соотношение.
Да, можно, но с использованием кода платформы. Я скоро обновлю свой ответ.
@ToolmakerSteve Большое спасибо за ваше предложение. Я не учел этот момент и теперь пытаюсь получить ширину и высоту с помощью кода платформы.
@copang Я обновил свой ответ, чтобы получить ширину и высоту изображения, а затем коэффициент подсчета. Вы могли бы попробовать.
О какой ОС идет речь? Кроме того, как вы думаете, это функция "AspectFit"?