Нарисуйте линию на 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
, чтобы правильно реагировать на изменения ориентации / макета).