C# 是否在Xamarin.iOS中使用带填充的UILabel?

C# 是否在Xamarin.iOS中使用带填充的UILabel?,c#,ios,iphone,xamarin.ios,uilabel,C#,Ios,Iphone,Xamarin.ios,Uilabel,我正在尝试在我的Xamarin.iOS应用程序中创建一个带有填充的UILabel。本机Objective-C应用程序中最流行的解决方案是覆盖drawTextInRect: - (void)drawTextInRect:(CGRect)rect { UIEdgeInsets insets = {0, 5, 0, 5}; return [super drawTextInRect:UIEdgeInsetsInsetRect(rect, insets)]; } 这看起来很简单,但我不太

我正在尝试在我的Xamarin.iOS应用程序中创建一个带有填充的
UILabel
。本机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

有什么建议吗?

ObjC函数的C#等价物
UIEdgeInsetsInsetRect
是名为
InsetRect
UIEdgeInsets
的实例方法,它与您的
RectangleF
计算不同(这可能是您的问题)

要使用它,您可以执行以下操作:

public override void DrawText(RectangleF rect)
{
    base.DrawText (Insets.InsetRect (rect));
}

我创建了一个通用的Padding UIView类,它封装了从UIView派生的任何IOS UI元素

基本上,它将所需的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
var myPaddedView=new PaddedUIView();
myPaddedView.Frame=实际帧;
myPaddedView.Padding=15f
myPaddedView.NestedView.Text=“你好,填充世界”//所有标签属性都可用,没有副作用
下面是课堂:

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(); }
    }
}
public类PaddedUIView:UIView其中T:UIView,new()
{
私人浮动(padding);;
私人T_nestedView;
公共PaddedUIView()
{
初始化();
}
公共填充视图(矩形边界)
:基本(边界)
{
初始化();
}
void Initialize()
{   
如果(_nestedView==null)
{ 
_nestedView=newt();
this.AddSubview(_nestedView);
}
_nestedView.Frame=新矩形F(_padding,_padding,Frame.Width-2*_padding,Frame.Height-2*_padding);
}
公共T嵌套视图
{ 
获取{return\u nestedView;}
}
公共浮子填充
{
获取{return\u padding;}
设置{if(value!={u padding=value;Initialize();}}
}

公共覆盖矩形框架 { 获取{return base.Frame;} set{base.Frame=value;Initialize();} } }
与其重写UILabel子类中的DrawText(),不如重写其固有的内容大小。这样,自动布局会考虑填充。例如,以下是我的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
    );
}

自给出最初的答案以来,正确的方法似乎略有改变,我花了一段时间才弄明白新的正确语法。这是给任何偶然发现这一点的人的。此代码将在视图的左侧和右侧放置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));
}
您必须覆盖
DrawText
和。 如果不重写
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));
    }
}

谢谢这似乎是Objective-C版本的正确翻译。它会按预期移动文本,但文本会被剪裁到右侧。换句话说,
UILabel
不会调整大小以适应插入。不过,这可能是一个单独的问题。该代码只会更改图形,因此
UILabel
不知道插入(并且不会更改其行为)。这是有道理的。在确定标签宽度时,我应该考虑插图的内容,有什么建议吗?如果可能的话,我希望它能动态调整大小。我不确定你想要的是什么样的结果-但是在这方面有很多类似的问题,例如,你可能想研究(并转换为C)。如果没有任何东西符合你的需要,那么再问另一个(更精确的,例如图片)问题寻求帮助。谢谢——我发布了一个屏幕截图:public override RectangleF Frame,这个方法无法解决问题