Xamarin Forms Ширина заливки изображения с соответствующим аспектом

Вот xaml (изображение в stacklayout). Все логично: я установил Aspect для AspectFit и HorizontalOptions в FillAndExpand. Ширина изображения должна заполнять ширину stacklayout. Высота должна быть рассчитана для изображения Aspect.

<Image BackgroundColor="Fuchsia"
       Aspect="AspectFit"
       Source="{Binding GroupLogo}"
       HorizontalOptions="FillAndExpand"
       VerticalOptions="FillAndExpand"/>

Он заполняет ширину, но не хочет рисовать полную ширину изображения. Почему?

введите описание изображения здесь

Ответ 1

AspectFit делает то, что он говорит на олове, он поместит все изображение в представление, которое может оставить части представления пустыми. Прямо из документации Xamarin:

Масштабируйте изображение, чтобы оно соответствовало виду. Некоторые части могут быть пустыми (буквенный бокс).

То, что вы ищете, это AspectFill, который масштабирует изображение в соответствии с:

Масштабируйте изображение, чтобы заполнить представление. Некоторые части могут быть обрезаны, чтобы заполнить представление.

Если вы пытаетесь получить представление изображения как высоту изображения, я бы предложил добавить HeightRequest к высоте изображения. По-моему, элементы управления изображением, по моему опыту, автоматически не масштабируются в Xamarin, поскольку встроенные элементы управления также не поддерживают это по умолчанию.

Ссылка

Ответ 2

У меня была аналогичная проблема. Я хотел заполнить ширину и высоту StackLayout, когда это возможно, но без обрезки фактического изображения. Ответы здесь помогли мне найти правильный путь. Вот что сработало для меня:

            <Grid 
                HorizontalOptions="FillAndExpand"
                VerticalOptions="FillAndExpand"
                 >
                <Image
                   x:Name="photo"                         
                   Aspect="AspectFit"                    
                />
            </Grid>

Возможно, это будет полезно для кого-то.

Разъяснение:

HorizontalOptions и VerticalOptions имеют значение FillAndExpand, поэтому высота и ширина сетки настраиваются для заполнения родителя, в этом случае это Stacklayout. Изображение является дочерним элементом сетки, поэтому оно преобразуется в соответствии с родительским (мы не предоставляли никаких дополнительных параметров изображению).

Аспект изображения установлен в AspectFit, так что изображение будет соответствовать представлению (в данном случае Grid), а также сохранить его отношения.

Таким образом, если изображение находится в портретном режиме, но слишком узкое, оно заполняет высоту сетки (StackLayout), но не заполняет ширину, чтобы сохранить свои отношения и не обрезаться сверху или снизу.

Если изображение находится в ландшафтном режиме, оно заполняет ширину сетки (StackLayout), но не заполняет высоту, чтобы сохранить ее отношения и не обрезаться слева или справа.

Ответ 3

Как я не нашел рабочего примера. Это прекрасно работает для меня:

<Grid VerticalOptions="FillAndExpand">
      <Image Source="{Binding MyImageSrc}" Aspect="AspectFill" />
</Grid>

Ответ 4

Aspect = "AspectFit" используется для размещения вашего изображения внутри макета, оно может оставить пространство, если изображения маленькие. Aspect = "AspectFill" используется для размещения вашего изображения внутри макета, и оно растянет ваше изображение, чтобы занять все пространство, и не оставит места, либо ваше изображение будет маленьким по сравнению с вашим родительским пространством макета. Таким образом, вы должны использовать AspectFill вместо AspectFit.

Ответ 5

Попробуйте включить изображение внутри сетки, например:

<grid>
    <image></image>
</grid>

Иногда, когда у меня есть изображение, которое не изменяется правильно, включение его в сетку решает проблему.

Ответ 6

Попробуйте использовать CachedImage из FFImageLoading Пакет NuGet

MyPage.xaml

<StackLayout HorizontalOptions="FillAndExpand"
             VerticalOptions="FillAndExpand"
             Padding="0">
    <ff:CachedImage Source="{Binding GroupLogo}"
                    HorizontalOptions="Fill"
                    VerticalOptions="Fill"
                    Aspect="Fill"
                    DownsampleToViewSize="True"/>
</StackLayout>

Это приведет к тому, что изображение попытается горизонтально заполнить контейнер и автоматически сгенерировать ширину при сохранении ее аспекта.

Добавьте эту строку кода в MainActivity.xaml после global::Xamarin.Forms.Forms.Init(this, bundle);

CachedImageRenderer.Init(true);

Пример можно найти здесь

Ответ 7

heightrequest из stacklayout должен быть либо StartAndExpand, либо FillAndExpand или EndAndExpand, чтобы автоматически регулировать высоту

Ответ 8

Это требует пользовательского рендеринга для обеих платформ. Создайте FillScreenImageRenderer, который наследуется от ImageRenderer.

<local:FillScreenImage Source="{ImageSource}"></local:FillScreenImage>

Код ниже растягивается на весь экран. Вы можете настроить границы представления так, чтобы они подходили к чему угодно, например, в вашем случае это родительское представление.

IOS:

    protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
    {
        base.OnElementChanged(e);
        UIGraphics.BeginImageContext(UIScreen.MainScreen.Bounds.Size);
        Control.Image.Draw(UIScreen.MainScreen.Bounds);
        var dest = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();
        Control.Image = dest;
    }

Android:

    protected override void OnElementChanged(ElementChangedEventArgs<Image> e)
    {
        base.OnElementChanged(e);
        var display = ((Activity)Context).WindowManager.DefaultDisplay;
        var b = ((BitmapDrawable)Control.Drawable).Bitmap;
        Bitmap bitmapResized = Bitmap.CreateScaledBitmap(b, display.Width, display.Height, false);
        Control.SetImageDrawable(new BitmapDrawable(Resources, bitmapResized));
    }