2014-12-09 2 views
0

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

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. Auto Layout определяет размер GradientView, и мое старое решение также адаптировано к изменениям ориентации.

Edit:

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

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(); 
    } 
} 

Это, кажется, делать то, что я хочу, за исключением того, что линия не тонкая линия волос. Is 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

+0

Многие вопросы по SO уже рассматривают эту проблему: http://stackoverflow.com/questions/21515451/draw-a-line-with-a-calayer, http://stackoverflow.com/questions/21515451/draw-a- line-with-a-calayer ... – Cyrille

+0

Другой вопрос: Почему 'UIView' получает черный фон, когда я реализую' drawRect'? Кажется, я не могу отключить сглаживание, не получив текущий графический контекст (например, [отключить сглаживание для UIBezierPath] (http://stackoverflow.com/questions/15417410/disable-anti-aliasing-for-uibezierpath)). Но поскольку я знаю, что текущий графический контекст доступен только в 'drawRect', который я снова не могу реализовать. – testing

Смежные вопросы