UIView с закругленными углами: как правильно обрезать подпредставления? - PullRequest
18 голосов
/ 07 ноября 2011

Я создал подкласс UIView, который переопределяет drawRect: и использует AddArcToPoint() для рисования закругленных углов. (Я не хочу использовать свойство угла радиуса слоя, потому что мне нужно определить, какие углы должны быть округлены.) Однако проблема, с которой я не могу справиться: если я добавлю подпредставление в (0 | 0), оно закроет мои круглые углы. Любая идея, как я могу это исправить? Я хотел бы, чтобы это красиво обрезалось.

Вот код, который рисует прямоугольник с закругленными углами. Это Monotouch, но должен быть понятен любому разработчику.

(полный код можно найти здесь: https://github.com/Krumelur/RoundedRectView)

public override void Draw (RectangleF rect)
        {
            using (var oContext = UIGraphics.GetCurrentContext())
            {
                oContext.SetLineWidth (this.StrokeWidth);
                oContext.SetStrokeColor (this.oStrokeColor.CGColor);
                oContext.SetFillColor (this.oRectColor.CGColor);

                RectangleF oRect = this.Bounds;

                float fRadius = this.CornerRadius;
                float fWidth = oRect.Width;
                float fHeight = oRect.Height;

                // Make sure corner radius isn't larger than half the shorter side.
                if (fRadius > fWidth / 2.0f)
                {
                    fRadius = fWidth / 2.0f;
                }
                if (fRadius > fHeight / 2.0f)
                {
                    fRadius = fHeight / 2.0f;    
                }

                float fMinX = oRect.GetMinX ();
                float fMidX = oRect.GetMidX ();
                float fMaxX = oRect.GetMaxX ();
                float fMinY = oRect.GetMinY ();
                float fMidY = oRect.GetMidY ();
                float fMaxY = oRect.GetMaxY ();

                // Move to left middle.
                oContext.MoveTo (fMinX, fMidY);

                // Arc to top middle.
                oContext.AddArcToPoint (fMinX, fMinY, fMidX, fMinY, (this.RoundCorners & ROUND_CORNERS.TopLeft) == ROUND_CORNERS.TopLeft ? fRadius : 0);
                // Arc to right middle.
                oContext.AddArcToPoint (fMaxX, fMinY, fMaxX, fMidY, (this.RoundCorners & ROUND_CORNERS.TopRight) == ROUND_CORNERS.TopRight ? fRadius : 0);
                // Arc to bottom middle.
                oContext.AddArcToPoint (fMaxX, fMaxY, fMidX, fMaxY, (this.RoundCorners & ROUND_CORNERS.BottomRight) == ROUND_CORNERS.BottomRight ? fRadius : 0);
                // Arc to left middle.
                oContext.AddArcToPoint (fMinX, fMaxY, fMinX, fMidY, (this.RoundCorners & ROUND_CORNERS.BottomLeft) == ROUND_CORNERS.BottomLeft ? fRadius : 0);

                // Draw the path.
                oContext.ClosePath ();
                oContext.DrawPath (CGPathDrawingMode.FillStroke);
            }
        }

EDIT:

Вот фрагмент кода, который демонстрирует, как решить эту проблему с помощью CALayer.

private void UpdateMask()
        {
            UIBezierPath oMaskPath = UIBezierPath.FromRoundedRect (this.Bounds, this.eRoundedCorners, new SizeF (this.fCornerRadius, this.fCornerRadius));

            CAShapeLayer oMaskLayer = new CAShapeLayer ();
            oMaskLayer.Frame = this.Bounds;
            oMaskLayer.Path = oMaskPath.CGPath;
            this.Layer.Mask = oMaskLayer;
        }

Ответы [ 2 ]

8 голосов
/ 07 ноября 2011

Я не пробовал, но я думаю, что вы можете использовать свойство маски CALayer для этого. Вы должны нарисовать прямоугольник со скругленными углами в слое, который был установлен в качестве маски для вашего слоя просмотра.

2 голосов
/ 07 ноября 2011

Можно (и, на самом деле, очень просто) указать конкретные закругленные углы, не прибегая к drawRect: или вручную нарисовав частично скругленный прямоугольник в слой.См. мой ответ на аналогичный вопрос.

...