2014-12-09 60 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