Несоответствие размера изображения Xamarin

Я использую кросс-платформенное приложение с использованием Xamarin Forms, и я борюсь со странной ошибкой: Я пытаюсь создать кнопку с текстом на ней. Для этого я использую AbsoluteLayout.

Я добавил изображение в проект iOS для каждого типа разрешений iOS (.png, @2x.png, @3x.png). Все работает нормально со стандартным тегом <Image />. Однако при обёртывании изображения в абсолютном макете изображение теряет пропорции разрешения и приводит к границам.

Код выше:

    <AbsoluteLayout BackgroundColor="Blue">
        <Image Source="home/donation-button.png"
            AbsoluteLayout.LayoutFlags="All" 
                x:Name="Button"
            AbsoluteLayout.LayoutBounds="0, 0, 1, 1" 
            />
        <Label Text="Hello, World!"
                TextColor="White"
                FontAttributes="Bold"
                FontSize="16"
                AbsoluteLayout.LayoutFlags="All"
                AbsoluteLayout.LayoutBounds="0, 1, 1, 0.5" />
    </AbsoluteLayout> 

Произведите следующее:

на iPhone 6 +/6s +/7 + (симулятор iPhone 7 Plus): Допустимое изображение на iPhone 7 Plus Это ожидаемое поведение.

на iPhone 6/6s/7 (симулятор iPhone 7): Обратите внимание на маленькие синие границы на изображении Обратите внимание на маленькие синие границы изображения, которые были установлены в качестве фона на AbsoluteLayout

на 5SE/5s и вниз: Обратите внимание на синие границы Обратите внимание на большие синие границы.

Чтобы отладить это, я поместил одно и то же изображение дважды - сначала в AbsoluteLayout, а затем в качестве стандартного элемента внутри StackLayout. Изображение в абсолютном макете имеет ошибку пропорции, и изображение без него не имеет.

Я немного потерялся здесь. Есть ли способ взломать этот путь? Я пытался создать. пользовательский рендерер, чтобы назначить размер изображения вручную, но похоже, что UIImage предоставляет различные единицы размера, которые использует Xamarin, и это не решит проблему на Android.

Любые советы будут действительно оценены!

Изменить (3/5/2017): Просто чтобы вы обновили - похоже, это общая ошибка в Xamarin Forms. Мое опубликованное решение является обходным решением, и я снова и снова застревает в этой проблеме.

Например, я пытаюсь создать этот графический интерфейс: Желаемый образ графического интерфейса пользователя

Я создал код ниже:

<StackLayout Orientation="Horizontal" 
            VerticalOptions="End"
            HorizontalOptions="FillAndExpand"
            BackgroundColor="#dd2c00">
            <Label Text="100"
                FontSize="46"
                Margin="10"
                FontFamily="OpenSans-Bold" 
                TextColor="#ffffff"
                VerticalOptions="FillAndExpand"
                VerticalTextAlignment="Center"
                HorizontalTextAlignment="Center" />
            <Label TextColor="#ffffff"
                FontSize="Medium"
                VerticalOptions="FillAndExpand"
                HorizontalOptions="FillAndExpand"
                VerticalTextAlignment="Center">
                <Label.FormattedText>
                    <FormattedString>
                        <Span FontFamily="OpenSans-Regular" Text="{markup:Localize CandlesMap.FacebookFriendsCandles1}" />
                        <Span FontFamily="OpenSans-Light" Text="{markup:Localize CandlesMap.FacebookFriendsCandles2}" />
                    </FormattedString>
                </Label.FormattedText>
            </Label>
            <Image Source="{markup:ResolvePath map.show_friends_candle_button}" />
        </StackLayout>

Все работает нормально, пока я не добавлю изображение, что приводит к следующему результату: Фактический GUI

Если кто-то подскажет, как взломать его, я буду очень признателен, если он или она сможет опубликовать решение здесь! Пока я получаю это, проблема с iOS UIImage renderer - конечная точка UIImage недоступна при вычислении макета изображения (и, следовательно, ширина и высота изображения -1), и поэтому XF не знает, как визуализируйте изображение правильно.

Ответ 1

Спасибо за предложенные ответы. К сожалению, эта проблема не была решена с использованием любого предлагаемого ответа. Я отказался от использования AbsoluteLayout. Фактически, на прошлой неделе я столкнулся со многими проблемами относительно изображений в iOS на RelativeLayout и StackLayout. Я сообщил им о Ксамарине.

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

using System;
using Xamarin.Forms;
namespace App.Views.Home
{
    public class DonationButton : RelativeLayout
    {
        #region Properties

        /// <summary>
        /// Gets or sets the button text.
        /// </summary>
        /// <value>The text.</value>
        public string Text
        {
            get { return this._textLabel.Text; }
            set { this._textLabel.Text = value; }
        }

        public event EventHandler Clicked;

        #endregion

        #region iVars

        private Image _backgroundImage;
        private Label _textLabel;

        #endregion

        public DonationButton()
        {
            //--------------------------------------------
            //  Setup the background image
            //--------------------------------------------
            this._backgroundImage = new Image()
            {
                Source = ImageSource.FromFile("home__donation_button.png")
            };

            this.Children.Add(this._backgroundImage, (Constraint)null, (Constraint)null, (Constraint)null, (Constraint)null);

            //--------------------------------------------
            //  Add the label
            //--------------------------------------------

            /* See: http://stackoverflow.com/a/40942692/1497516 */
            Func<RelativeLayout, double> getLabelWidth
                = (p) => this._textLabel.Measure(p.Width, p.Height).Request.Width;
            Func<RelativeLayout, double> getLabelHeight
                = (p) => this._textLabel.Measure(p.Width, p.Height).Request.Height;

            this._textLabel = new Label()
            {
                TextColor = Color.White,
                FontAttributes = FontAttributes.Bold,
                FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
            };

            this.Children.Add(this._textLabel,
                              Constraint.RelativeToParent((parent) => parent.Width - (getLabelWidth(parent) + 10)),
                              Constraint.RelativeToView(this._backgroundImage, (parent, view) => (view.Height - getLabelHeight(parent)) / 2)
                              );

            //--------------------------------------------
            //  Allow clicks
            //--------------------------------------------
            this.GestureRecognizers.Add(new TapGestureRecognizer
            {
                Command = new Command(sender =>
                {
                    if (this.Clicked != null)
                    {
                        this.Clicked(sender, EventArgs.Empty);
                    }
                }),
                NumberOfTapsRequired = 1
            });
        }
    }
}

Ответ 2

Вы можете установить свойство Aspect тега изображения в AspectFill, которое позволяет вашему изображению соответствовать его контейнеру, не теряя его разрешения.

<AbsoluteLayout BackgroundColor="Blue">
        <Image Source="home/donation-button.png"
            Aspect="AspectFill"
            AbsoluteLayout.LayoutFlags="All" 
            x:Name="Button"
            AbsoluteLayout.LayoutBounds="0, 0, 1, 1"/>
        <Label Text="Hello, World!"
            TextColor="White"
            FontAttributes="Bold"
            FontSize="16"
            AbsoluteLayout.LayoutFlags="All"
            AbsoluteLayout.LayoutBounds="0, 1, 1, 0.5" />
    </AbsoluteLayout>

`

Ответ 3

Граница и изменение размера - от AbsoluteLayout, а не от изображения. Посмотрите, может ли ширина макета динамически расширяться как 100% из родительского контейнера, и если она разрешает такие параметры, как no-border.

Ответ 4

Просто добавьте

Aspect:AspectFill

или

Fill

в зависимости от ваших потребностей!!!

Ответ 5

попробуйте использовать Горизонтальный StackLayout как следующий:

<StackLayout BackgroundColor="Blue" Orientation="Horizontal">
        <Image Source="home/donation-button.png"               
            x:Name="Button"
            />
        <Label Text="Hello, World!"
            TextColor="White"
            FontAttributes="Bold"
            FontSize="16"
           />
    </StackLayout >