Ios Xamarin自定义呈现程序ContentView问题

Ios Xamarin自定义呈现程序ContentView问题,ios,xaml,xamarin,custom-renderer,Ios,Xaml,Xamarin,Custom Renderer,我已经为iOS编写了一个自定义渲染器,以编程方式创建聊天泡泡。主聊天泡泡继承自ContentView,这样做是为了允许我添加一个标签作为它的唯一子项。在大多数情况下,它工作得很好,但一旦出现多行文本,它的行为就会非常奇怪,即文本溢出,不尊重父母的界限(让我想起我十几岁时的情景) 当我用常规框架替换这个自定义控件时,一切似乎都很好。我通过重写Draw(CGRect)调用来计算所需的高度 代码如下: ppublic class ChatBubbleRenderer : VisualElementRe

我已经为iOS编写了一个自定义渲染器,以编程方式创建聊天泡泡。主聊天泡泡继承自ContentView,这样做是为了允许我添加一个标签作为它的唯一子项。在大多数情况下,它工作得很好,但一旦出现多行文本,它的行为就会非常奇怪,即文本溢出,不尊重父母的界限(让我想起我十几岁时的情景)

当我用常规框架替换这个自定义控件时,一切似乎都很好。我通过重写Draw(CGRect)调用来计算所需的高度

代码如下:

ppublic class ChatBubbleRenderer : VisualElementRenderer<ChatBubbleFrame>
{
    public ChatBubbleRenderer()
    {
        this.ClipsToBounds = false;
    }

    public override void Draw(CGRect rect1)
    {
        var rect = Frame;
        var currentContext = UIGraphics.GetCurrentContext();
        var properRect = AdjustForThickness(rect);
        HandleShapeDraw(currentContext, properRect);
    } 

    protected RectangleF AdjustForThickness(CGRect rect)
    {
        var x = rect.X + Element.Padding.Left;
        var y = rect.Y + Element.Padding.Top;
        var width = rect.Width - ((Element.Padding.Left + (int)Element.StrokeWidth) * 2);
        var height = rect.Height - ((Element.Padding.Top + (int)Element.StrokeWidth) * 2);
        return new RectangleF((float)x, (float)y, (float)width, (float)height);
    }

    protected void HandleShapeDraw(CGContext currentContext, RectangleF rect)
    {
        var path = new CGPath();
        var cr = (float)Element.CornerRadius;
        var hl = (float)Element.HandleLength;
        var x = rect.Left+hl;
        var y = (float)rect.Top;

        var startLeft = x;
        var startTop = y;
        var startRight = rect.Right - hl;
        var startBottom = rect.Bottom ;
        var centerX = x + cr;
        var centerY = y + cr;
        var width = (float)rect.Width - hl - hl;
        var height = (float)rect.Height ;

        if (Element.HandleIsBottomRight)
        {
            path.AddArc(centerX, centerY, cr, (float)Math.PI, (float)Math.PI * 3f / 2f, false);
            x = startRight - cr;
            //line to top right arc
            path.AddLineToPoint(x, y);

            //top right arc
            centerX = x;
            path.AddArc(centerX, centerY, cr, (float)Math.PI * 3f / 2f, 0, false);
            x = x + cr;

            //bring y down to top of triangle
            y = y + height;
            path.AddLineToPoint(x, y);

            //chat handle
            x = x + hl;
            y = y + hl;
            path.AddLineToPoint(x, y);
            //to bottom left arc

            x = startLeft + cr;
            path.AddLineToPoint(x, y);

            //bottom left arc
            centerX = x;
            centerY = y - cr;
            path.AddArc(centerX, centerY, cr, (float)Math.PI / 2f, (float)Math.PI, false); //false to rotate clockwise
        }
        else
        {
            //line to top right arc
            path.MoveToPoint(x, y);
            x = startRight - cr;
            path.AddLineToPoint(x, y);

            //top right arc
            centerX = x;
            path.AddArc(centerX, centerY, cr, (float)Math.PI * 3f / 2f, 0, false);

            //line to bottom right arc
            x = x + cr;
            y = y + height - cr;
            path.AddLineToPoint(x, y);

            //bottom right arc
            centerX = x - cr;
            centerY = y;
            path.AddArc(centerX, centerY, cr, 0f, (float)Math.PI / 2f, false);

            //line to bottom left arc
            x = startLeft + cr;
            y = y + cr;
            path.AddLineToPoint(x, y);

            //bottom left arc
            centerX = x;
            centerY = y - cr;
            path.AddArc(centerX, centerY, cr, (float)Math.PI / 2f, (float)Math.PI, false); //false to rotate clockwise

            //line to handle
            x = startLeft;
            y = startTop + hl;
            path.AddLineToPoint(x, y);
            x = x - hl;
            y = startTop;
            path.AddLineToPoint(x, y);
        } 

        path.CloseSubpath();
        HandleStandardDraw(currentContext, rect, () => currentContext.AddPath(path));
    }

    /// <summary>
    /// A simple method for handling our drawing of the shape. This method is called differently for each type of shape
    /// </summary>
    /// <param name="currentContext">Current context.</param>
    /// <param name="rect">Rect.</param>
    /// <param name="createPathForShape">Create path for shape.</param>
    /// <param name="lineWidth">Line width.</param>
    protected virtual void HandleStandardDraw(CGContext currentContext, RectangleF rect, Action createPathForShape, float? lineWidth = null)
    {
        currentContext.SetLineWidth(lineWidth ?? Element.StrokeWidth);
        currentContext.SetFillColor(Element.InnerColor.ToCGColor());
        currentContext.SetStrokeColor(Element.StrokeColor.ToCGColor());

        createPathForShape();

        currentContext.DrawPath(CoreGraphics.CGPathDrawingMode.FillStroke);
    }
}