2014-12-09 56 views
0

我创建了一个UIView子类,它的图层使用CAGradientLayer。这工作正常。现在我想在渐变的末尾绘制一条线(用作分隔符)。我以为我可以使用这个方法drawRect用CAGradientLayer作为后备存储在UIView上画线

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以对方向/布局更改作出正确反应)。

+0

感谢您的回复。我尝试了你所说的和它的工作原理。但有一个问题:我怎样才能用CAShapeLayer绘制一条细线? – testing 2014-12-09 12:28:10

+0

关于SO的许多问题已经解决了这个问题:http://stackoverflow.com/questions/21515451/draw-a-line-with-a-calayer,http://stackoverflow.com/questions/21515451/drawa-a-一行一行... – Cyrille 2014-12-09 13:14:30

+0

另一个问题:为什么'UIView'在我实现'drawRect'时得到黑色背景?似乎我无法关闭消除锯齿而没有获取当前的图形上下文(例如[禁用UIBezierPath的抗锯齿](http://stackoverflow.com/questions/15417410/disable-anti-aliasing-for-uibezierpath) )。但据我所知,当前的图形上下文只能在'drawRect'中使用,我再次无法实现。 – testing 2014-12-09 13:18:31