Я создал подкласс 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);
}
Спасибо за ваш ответ. Я попробовал то, что вы сказали, и это работает. Один вопрос: как я могу нарисовать тонкую главу с 'CAShapeLayer'? – testing
Многие вопросы по SO уже рассматривают эту проблему: http://stackoverflow.com/questions/21515451/draw-a-line-with-a-calayer, http://stackoverflow.com/questions/21515451/draw-a- line-with-a-calayer ... – Cyrille
Другой вопрос: Почему 'UIView' получает черный фон, когда я реализую' drawRect'? Кажется, я не могу отключить сглаживание, не получив текущий графический контекст (например, [отключить сглаживание для UIBezierPath] (http://stackoverflow.com/questions/15417410/disable-anti-aliasing-for-uibezierpath)). Но поскольку я знаю, что текущий графический контекст доступен только в 'drawRect', который я снова не могу реализовать. – testing