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