Нарисуйте линию на UIView с CAGradientLayer в качестве резервного магазина

Я создал UIView подкласс, который использует CAGradientLayer для его слоя. Это работает нормально. Теперь я хочу нарисовать линию в конце градиента (используется в качестве разделителя). Я думал, что могу использовать drawRect метод для этого:

public class GradientView : UIView
{
    // accessors
    private CAGradientLayer gradientLayer {
        // read-only
        get { return (CAGradientLayer)this.Layer; }
    }

    public CGColor[] Colors {
        // set the colors of the gradient layer
        get { return this.gradientLayer.Colors; }
        set { this.gradientLayer.Colors = value; }
    }

    [Export ("layerClass")]
    public static Class LayerClass ()
    {
        // use a different Core Animation layer for its backing store
        // normally a CALayer is used for a UIView
        return new Class (typeof(CAGradientLayer));
    }

    public override void Draw (RectangleF rect)
    {

        PointF pointA = new PointF (0, rect.Height);
        PointF pointB = new PointF (rect.Width, rect.Height);
        CAShapeLayer line = new CAShapeLayer ();
        UIBezierPath linePath = new UIBezierPath ();
        linePath.MoveTo (pointA);
        linePath.AddLineTo(pointB);
        line.Path = linePath.CGPath;
        line.FillColor = null;
        line.Opacity = 1.0f;
        line.StrokeColor = UIColor.Black.CGColor;

        this.gradientLayer.AddSublayer (line);

        base.Draw (rect);
    }
}

Но я получаю черный фон. Могу ли я использовать drawRect для этого? Или как мне добавить строку?

Я использую C# в качестве языка, но вы также можете предоставить свое решение в Objective-C. Авто макет определяет размер GradientView и мое старое решение также адаптировано к изменениям ориентации.

Редактировать:

Я попробовал то, что сказал Кирилл:

public class GradientView : UIView
{
    // accessors
    private CAShapeLayer line;

    private CAGradientLayer gradientLayer {
        // read-only
        get { return (CAGradientLayer)this.Layer; }
    }

    public CGColor[] Colors {
        // set the colors of the gradient layer
        get { return this.gradientLayer.Colors; }
        set { this.gradientLayer.Colors = value; }
    }

    public GradientView()
    {
        PointF pointA = new PointF (0, this.Bounds.Height);
        PointF pointB = new PointF (this.Bounds.Width, this.Bounds.Height);
        line = new CAShapeLayer ();
        UIBezierPath linePath = new UIBezierPath ();
        linePath.MoveTo (pointA);
        linePath.AddLineTo(pointB);
        line.Path = linePath.CGPath;
        line.FillColor = null;
        line.Opacity = 1.0f;
        line.StrokeColor = UIColor.Black.CGColor;
        line.LineWidth = 1.0f;

        this.gradientLayer.AddSublayer (line);
    }

    [Export ("layerClass")]
    public static Class LayerClass ()
    {
        // use a different Core Animation layer for its backing store
        // normally a CALayer is used for a UIView
        return new Class (typeof(CAGradientLayer));
    }

    public override void LayoutSubviews ()
    {
        PointF pointA = new PointF (0, this.Bounds.Height-2);
        PointF pointB = new PointF (this.Bounds.Width, this.Bounds.Height-2);
        UIBezierPath linePath = new UIBezierPath ();
        linePath.MoveTo (pointA);
        linePath.AddLineTo(pointB);

        line.Path = linePath.CGPath;

        base.LayoutSubviews ();
    }
}

Это, кажется, делает то, что я хочу, за исключением того, что линия не тонкая линия волос. Является CAShapeLayer не подходит для этого?

Решение:

Конечно, можно было бы использовать CAShapeLayer, но если мне нужно настроить вещи в drawRectтогда я полностью рисую свою линию там. Теперь решение для меня выглядит следующим образом:

public class GradientView : UIView
{
    // accessors
    private CAShapeLayer line;

    private CAGradientLayer gradientLayer {
        // read-only
        get { return (CAGradientLayer)this.Layer; }
    }

    public CGColor[] Colors {
        // set the colors of the gradient layer
        get { return this.gradientLayer.Colors; }
        set { this.gradientLayer.Colors = value; }
    }

    public GradientView()
    {
        this.BackgroundColor = UIColor.Clear;
    }

    [Export ("layerClass")]
    public static Class LayerClass ()
    {
        // use a different Core Animation layer for its backing store
        // normally a CALayer is used for a UIView
        return new Class (typeof(CAGradientLayer));
    }

    public override void Draw (RectangleF rect)
    {
        base.Draw (rect);

        // get graphics context
        CGContext context = UIGraphics.GetCurrentContext ();

        // start point
        context.MoveTo (0, rect.Height);

        // end point
        context.AddLineToPoint (rect.Width, rect.Height);

        context.SetLineWidth (1.0f);

        context.SetShouldAntialias(false);

        // draw the path
        context.DrawPath (CGPathDrawingMode.Stroke);
    }

1 ответ

Решение

Используя CAGradientLayer поскольку поддерживающий слой вашего вида не мешает вам добавить другой CAShapeLayer внутри вашего взгляда на инициализацию. Затем вы можете использовать этот слой формы, чтобы нарисовать вашу прямую линию, установив его path свойство (и пересчитать его при каждом изменении границ, в -layoutSubviews, чтобы правильно реагировать на изменения ориентации / макета).

Другие вопросы по тегам