CAShapeLayer 在 XIB 中不可见 swift iOS
CAShapeLayer not visible in XIB swift iOS
我正在使用 XIB 文件构建自定义视图。但是,我遇到了一个问题,我添加到视图 (trackLayer) 的层没有显示在 xib 上(circleLayer 是一个动画,我不希望它在 xib 中呈现,据我所知这是不可能的)。 XIB的所有者class代码如下:
@IBDesignable
class SpinningView: UIView {
@IBOutlet var contentView: SpinningView!
//MARK: Properties
let circleLayer = CAShapeLayer()
let trackLayer = CAShapeLayer()
let circularAnimation: CABasicAnimation = {
let animation = CABasicAnimation()
animation.fromValue = 0
animation.toValue = 1
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
return animation
}()
//MARK: IB Inspectables
@IBInspectable var strokeColor: UIColor = UIColor.red {
...
}
@IBInspectable var trackColor: UIColor = UIColor.lightGray {
...
}
@IBInspectable var lineWidth: CGFloat = 5 {
...
}
@IBInspectable var fillColor: UIColor = UIColor.clear {
...
}
@IBInspectable var isAnimated: Bool = true {
...
}
//MARK: Initialization
override init(frame: CGRect) {
super.init(frame: frame)
initSubviews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
initSubviews()
}
//MARK: Private functions
private func setup() {
setupTrack()
setupAnimationOnTrack()
}
private func setupTrack(){
trackLayer.lineWidth = lineWidth
trackLayer.fillColor = fillColor.cgColor
trackLayer.strokeColor = trackColor.cgColor
layer.addSublayer(trackLayer)
}
private func setupAnimationOnTrack(){
circleLayer.lineWidth = lineWidth
circleLayer.fillColor = fillColor.cgColor
circleLayer.strokeColor = strokeColor.cgColor
circleLayer.lineCap = kCALineCapRound
layer.addSublayer(circleLayer)
updateAnimation()
}
private func updateAnimation() {
if isAnimated {
circleLayer.add(circularAnimation, forKey: "strokeEnd")
}
else {
circleLayer.removeAnimation(forKey: "strokeEnd")
}
}
//MARK: Layout contraints
override func layoutSubviews() {
super.layoutSubviews()
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let radius = min(bounds.width / 2, bounds.height / 2) - circleLayer.lineWidth / 2
let startAngle = -CGFloat.pi / 2
let endAngle = 3 * CGFloat.pi / 2
let path = UIBezierPath(arcCenter: .zero, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
trackLayer.position = center
trackLayer.path = path.cgPath
circleLayer.position = center
circleLayer.path = path.cgPath
}
private func initSubviews() {
let bundle = Bundle(for: SpinningView.self)
let nib = UINib(nibName: "SpinningView", bundle: bundle)
nib.instantiate(withOwner: self, options: nil)
contentView.frame = bounds
addSubview(contentView)
}
}
当视图在 Main.storyboard 中被子class 编辑时,我可以看到如下图像和轨道层 IB UIView but when I go over to the XIB, it does not have the trackLayer(circle around the image) XIB Image。虽然有人会争辩说它正在工作以及为什么我为此烦恼,但我认为正确设计 XIB 很重要,因为另一个人可能只是将它视为只有图像的视图(不知道动画功能)
当您设计 XIB 时,它不是 您的 @IBDesignable SpinningView
的 实例。实际上,您正在查看 SpinningView
.
的 source
因此,它背后的代码此时不是 运行 - 它仅在您将 SpinningView
的实例添加到另一个视图时运行。
看看这个简单的例子:
@IBDesignable
class SpinningView: UIView {
@IBOutlet var contentView: UIView!
@IBOutlet var theLabel: UILabel!
//MARK: Initialization
override init(frame: CGRect) {
super.init(frame: frame)
initSubviews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initSubviews()
}
private func initSubviews() {
let bundle = Bundle(for: SpinningView.self)
let nib = UINib(nibName: "SpinningView", bundle: bundle)
nib.instantiate(withOwner: self, options: nil)
contentView.frame = bounds
addSubview(contentView)
// this will change the label's textColor in Storyboard
// when a UIView's class is set to SpinningView
theLabel.textColor = .red
}
}
当我设计 XIB 时,这是我看到的:
但是当我将 UIView
添加到另一个视图,并将其 class 分配为 SpinningView
时,我看到的是:
标签的文本颜色更改为红色,因为代码现在是 运行。
另一种思考方式...您将 trackColor
、fillColor
等变量定义为 @IBInspectable
。当您设计 XIB 时,您不会在 Xcode 的属性检查器面板中看到这些属性 - 只有当您选择了已添加到其他地方的 SpinningView
实例时才会看到它们。
希望这是有道理的。
我正在使用 XIB 文件构建自定义视图。但是,我遇到了一个问题,我添加到视图 (trackLayer) 的层没有显示在 xib 上(circleLayer 是一个动画,我不希望它在 xib 中呈现,据我所知这是不可能的)。 XIB的所有者class代码如下:
@IBDesignable
class SpinningView: UIView {
@IBOutlet var contentView: SpinningView!
//MARK: Properties
let circleLayer = CAShapeLayer()
let trackLayer = CAShapeLayer()
let circularAnimation: CABasicAnimation = {
let animation = CABasicAnimation()
animation.fromValue = 0
animation.toValue = 1
animation.duration = 2
animation.fillMode = kCAFillModeForwards
animation.isRemovedOnCompletion = false
return animation
}()
//MARK: IB Inspectables
@IBInspectable var strokeColor: UIColor = UIColor.red {
...
}
@IBInspectable var trackColor: UIColor = UIColor.lightGray {
...
}
@IBInspectable var lineWidth: CGFloat = 5 {
...
}
@IBInspectable var fillColor: UIColor = UIColor.clear {
...
}
@IBInspectable var isAnimated: Bool = true {
...
}
//MARK: Initialization
override init(frame: CGRect) {
super.init(frame: frame)
initSubviews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
initSubviews()
}
//MARK: Private functions
private func setup() {
setupTrack()
setupAnimationOnTrack()
}
private func setupTrack(){
trackLayer.lineWidth = lineWidth
trackLayer.fillColor = fillColor.cgColor
trackLayer.strokeColor = trackColor.cgColor
layer.addSublayer(trackLayer)
}
private func setupAnimationOnTrack(){
circleLayer.lineWidth = lineWidth
circleLayer.fillColor = fillColor.cgColor
circleLayer.strokeColor = strokeColor.cgColor
circleLayer.lineCap = kCALineCapRound
layer.addSublayer(circleLayer)
updateAnimation()
}
private func updateAnimation() {
if isAnimated {
circleLayer.add(circularAnimation, forKey: "strokeEnd")
}
else {
circleLayer.removeAnimation(forKey: "strokeEnd")
}
}
//MARK: Layout contraints
override func layoutSubviews() {
super.layoutSubviews()
let center = CGPoint(x: bounds.midX, y: bounds.midY)
let radius = min(bounds.width / 2, bounds.height / 2) - circleLayer.lineWidth / 2
let startAngle = -CGFloat.pi / 2
let endAngle = 3 * CGFloat.pi / 2
let path = UIBezierPath(arcCenter: .zero, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)
trackLayer.position = center
trackLayer.path = path.cgPath
circleLayer.position = center
circleLayer.path = path.cgPath
}
private func initSubviews() {
let bundle = Bundle(for: SpinningView.self)
let nib = UINib(nibName: "SpinningView", bundle: bundle)
nib.instantiate(withOwner: self, options: nil)
contentView.frame = bounds
addSubview(contentView)
}
}
当视图在 Main.storyboard 中被子class 编辑时,我可以看到如下图像和轨道层 IB UIView but when I go over to the XIB, it does not have the trackLayer(circle around the image) XIB Image。虽然有人会争辩说它正在工作以及为什么我为此烦恼,但我认为正确设计 XIB 很重要,因为另一个人可能只是将它视为只有图像的视图(不知道动画功能)
当您设计 XIB 时,它不是 您的 @IBDesignable SpinningView
的 实例。实际上,您正在查看 SpinningView
.
因此,它背后的代码此时不是 运行 - 它仅在您将 SpinningView
的实例添加到另一个视图时运行。
看看这个简单的例子:
@IBDesignable
class SpinningView: UIView {
@IBOutlet var contentView: UIView!
@IBOutlet var theLabel: UILabel!
//MARK: Initialization
override init(frame: CGRect) {
super.init(frame: frame)
initSubviews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initSubviews()
}
private func initSubviews() {
let bundle = Bundle(for: SpinningView.self)
let nib = UINib(nibName: "SpinningView", bundle: bundle)
nib.instantiate(withOwner: self, options: nil)
contentView.frame = bounds
addSubview(contentView)
// this will change the label's textColor in Storyboard
// when a UIView's class is set to SpinningView
theLabel.textColor = .red
}
}
当我设计 XIB 时,这是我看到的:
但是当我将 UIView
添加到另一个视图,并将其 class 分配为 SpinningView
时,我看到的是:
标签的文本颜色更改为红色,因为代码现在是 运行。
另一种思考方式...您将 trackColor
、fillColor
等变量定义为 @IBInspectable
。当您设计 XIB 时,您不会在 Xcode 的属性检查器面板中看到这些属性 - 只有当您选择了已添加到其他地方的 SpinningView
实例时才会看到它们。
希望这是有道理的。