UILabel с заполнением в Xamarin.iOS?

Я пытаюсь создать UILabel с заполнением в моем приложении Xamarin.iOS. Самое популярное решение в нативных приложениях Objective-C - это переопределение drawTextInRect:

- (void)drawTextInRect:(CGRect)rect {
    UIEdgeInsets insets = {0, 5, 0, 5};
    return [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)];
}

Каким бы простым это ни казалось, я не могу понять, как перевести это на C #. Вот мой лучший удар:

internal class PaddedLabel : UILabel
{
    public UIEdgeInsets Insets { get; set; }

    public override void DrawText(RectangleF rect)
    {
        var padded = new RectangleF(rect.X + Insets.Left, rect.Y, rext.Width + Insets.Left + Insets.Right, rect.Height);

        base.DrawText(padded);
    }
}

Кажется, что это перемещает текст метки, но не меняет размер метки.

Я думаю, что основная проблема в том, что я не могу найти Xamarin-эквивалент UIEdgeInsetsInsetRect.

Какие-либо предложения?


person Josh Earl    schedule 16.01.2014    source источник


Ответы (5)


Эквивалент C # функции ObjC UIEdgeInsetsInsetRect является методом экземпляра UIEdgeInsets с именем InsetRect и не идентичен вашим RectangleF вычислениям (что вероятно является вашей проблемой).

Чтобы использовать его, вы можете:

public override void DrawText(RectangleF rect)
{
    base.DrawText (Insets.InsetRect (rect));
}
person poupou    schedule 16.01.2014
comment
Спасибо! Похоже, это правильный перевод версии Objective-C. Он сдвигает текст, как и ожидалось, но текст обрезается справа. Другими словами, UILabel не изменяет размер для размещения вставок. Хотя это может быть отдельный вопрос. - person Josh Earl; 16.01.2014
comment
Этот код изменяет только рисунок, поэтому UILabel не знает о вставке (и не изменяет ее поведение). - person poupou; 16.01.2014
comment
В этом есть смысл. Есть ли предложения относительно того, на что следует обратить внимание, чтобы учесть вставки при определении ширины этикетки? Я бы хотел, чтобы его размер изменялся динамически, если это возможно. - person Josh Earl; 16.01.2014
comment
Я не уверен, какой точный результат вы ищете, но есть много похожих вопросов по SO, например stackoverflow.com/q/6854991/220643, который вы, возможно, захотите изучить (и преобразовать в C #). Если ничто не соответствует вашим потребностям, задайте другой (более точный, например, с изображением) вопрос для получения помощи. - person poupou; 16.01.2014
comment
Спасибо - я опубликовал продолжение со снимком экрана: stackoverflow.com/questions/21167226/ - person Josh Earl; 16.01.2014
comment
Похоже, сейчас это обесценилось, см. Мой ответ ниже - person jnel899; 01.12.2017

Вам необходимо переопределить как DrawText, так и TextRectForBounds. Если вы не переопределите TextRectForBounds, текст будет обрезан. Фактически, вы переопределяете этот метод, чтобы компенсировать пространство, занимаемое заполнением, и просите iOS нарисовать текст в большем прямоугольнике.

public partial class LabelWithBorder
    : UILabel
{
    private UIEdgeInsets EdgeInsets = new UIEdgeInsets(5, 5, 5, 5);
    private UIEdgeInsets InverseEdgeInsets = new UIEdgeInsets(-5, -5, -5, -5);

    public LabelWithBorder(IntPtr handle) : base(handle)
    {
    }

    public override CoreGraphics.CGRect TextRectForBounds(CoreGraphics.CGRect bounds, nint numberOfLines)
    {
        var textRect = base.TextRectForBounds(EdgeInsets.InsetRect(bounds), numberOfLines);
        return InverseEdgeInsets.InsetRect(textRect);
    }

    public override void DrawText(CoreGraphics.CGRect rect)
    {
        base.DrawText(EdgeInsets.InsetRect(rect));
    }
}
person CoyBit    schedule 07.03.2018

Я создал общий класс Padding UIView, который охватывает любой элемент пользовательского интерфейса IOS, производный от UIView.

По сути, он вкладывает желаемый UIView в другое представление и берет на себя всю работу по заполнению.

использование:

var myPaddedView = new PaddedUIView<UILabel>();
myPaddedView.Frame = TheActualFrame;
myPaddedView.Padding = 15f
myPaddedView.NestedView.Text = "Hello padded world";  // all the label Properties are available without side effects

Вот класс:

public class PaddedUIView<T>: UIView where T : UIView, new()
{
    private float _padding;
    private T _nestedView;

    public PaddedUIView()
    {
        Initialize();
    }

    public PaddedUIView(RectangleF bounds)
        : base(bounds)
    {
        Initialize();
    }

    void Initialize()
    {   
        if(_nestedView == null)
        { 
            _nestedView = new T();
            this.AddSubview(_nestedView);
        }
        _nestedView.Frame =  new RectangleF(_padding,_padding,Frame.Width - 2 * _padding, Frame.Height - 2 * _padding);
    }

    public T NestedView
    { 
        get { return _nestedView; }
    }

    public float Padding
    {
        get { return _padding; }
        set { if(value != _padding) { _padding = value; Initialize(); }}
    }

    public override RectangleF Frame
    {
        get { return base.Frame; }
        set { base.Frame = value; Initialize(); }
    }
}
person spaceMonster    schedule 22.04.2014
comment
public override RectangleF Frame, этот метод не разрешает - person Signcodeindie; 29.04.2016

Вместо того, чтобы переопределять DrawText () в подклассе UILabel, переопределите его внутренний размер содержимого. Таким образом, автоматическая компоновка учитывает отступы. Например, вот мой производный класс от UILabel:

public class PaddedLabel : UILabel
{
    private readonly float _top;
    private readonly float _left;
    private readonly float _right;
    private readonly float _bottom;

    public PaddedLabel(float top, float left, float right, float bottom)
    {
        _top = top;
        _left = left;
        _right = right;
        _bottom = bottom;
    }

    public override CGSize IntrinsicContentSize => new CGSize(
        base.IntrinsicContentSize.Width + _left + _right,
        base.IntrinsicContentSize.Height + _top + _bottom
    );
}
person masterwok    schedule 20.10.2016

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

public override void DrawText(CGRect rect)
{
     rect.X = 5; 
     rect.Width = rect.Width - 10; // or whatever padding settings you want
     base.DrawText(AlignmentRectInsets.InsetRect(rect));
}
person jnel899    schedule 01.12.2017