使用CAGradientLayer作为后备存储在UIView上绘制线条

时间:2014-12-09 11:39:40

标签: ios uiview cashapelayer 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的大小,我的旧解决方案也适应方向更改。

修改

我试过Cyrille说的话:

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 个答案:

答案 0 :(得分:1)

使用CAGradientLayer作为视图的后备层并不会阻止您在初始化时在视图中添加其他CAShapeLayer。然后,您可以使用此形状图层来绘制直线,方法是相应地设置其path属性(并在-layoutSubviews中随时更改边界时重新计算它,以便对方向/布局更改做出正确反应)。