這不是做事的正確方法。每次您的RenderView
重新繪製時,將調用其drawRect
方法,並且addDashedBorder
將添加到您的視圖的新圖層。
drawRect
用於使用CoreGraphics或UIKit繪製視圖,而不是CoreAnimation。在這個方法裏面,你應該畫畫,沒有別的。如果你想使用它一層,layoutSubviews
是一個更好的地方添加它,並更新它以匹配視圖。
以下是解決問題的兩種方法。正確更新邊框,並在設備旋轉時平滑地設置邊框的動畫效果。
替代方案1:只需在drawRect
中繪製邊框,而不是使用單獨的形狀圖層。此外,請設置您的視圖contentMode
,以便在其大小更改時自動重新繪製。
class ViewController: UIViewController {
@IBOutlet weak var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.myView.contentMode = .Redraw
}
}
class RenderView: UIView {
override func drawRect(rect: CGRect) {
let path = UIBezierPath(roundedRect: self.bounds, cornerRadius: 5)
path.lineWidth = 6
let pattern: [CGFloat] = [6.0, 3.0]
path.setLineDash(pattern, count: 2, phase: 0)
UIColor.whiteColor().setStroke()
path.stroke()
}
}
選擇2:繼續使用CAShapeLayer
,但只能創建一個單獨的一個,用lazy stored property。在覆蓋layoutSubviews
的覆蓋中更新圖層,並在必要時將其與視圖邊界中的任何更改一起進行動畫處理。
class ViewController: UIViewController {
@IBOutlet weak var myView: UIView!
}
class RenderView: UIView {
// Create the borderLayer, and add it to our view's layer, on demand, only once.
lazy var borderLayer: CAShapeLayer = {
let shapeLayer = CAShapeLayer()
shapeLayer.fillColor = nil
shapeLayer.strokeColor = UIColor.whiteColor().CGColor
shapeLayer.lineWidth = 6
shapeLayer.lineDashPattern = [6,3]
self.layer.addSublayer(shapeLayer)
return shapeLayer
}()
override func layoutSubviews() {
super.layoutSubviews()
// We will update the borderLayer's path to match the view's current bounds.
let newPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: 5).CGPath
// We may be animating from the old bounds to the new bounds.
// If so, we want the borderLayer to animate alongside that.
// (UIView does not do this automatically, since it does not know
// anything about our borderLayer; it's at the the CoreAnimation level,
// below UIKit.)
//
// We want an animation that uses the same properties as the existing
// animation, but applies to a different value: the borderLayer's path.
// We'll find the existing animation on the view's bounds.size,
// and if it exists, add our own animation based on it that will
// apply the path change.
if let viewBoundsAnimation = self.layer.animationForKey("bounds.size") {
let pathAnimation = CABasicAnimation()
pathAnimation.beginTime = viewBoundsAnimation.beginTime
pathAnimation.duration = viewBoundsAnimation.duration
pathAnimation.speed = viewBoundsAnimation.speed
pathAnimation.timeOffset = viewBoundsAnimation.timeOffset
pathAnimation.timingFunction = viewBoundsAnimation.timingFunction
pathAnimation.keyPath = "path"
pathAnimation.fromValue = borderLayer.path
pathAnimation.toValue = newPath
borderLayer.addAnimation(pathAnimation, forKey: "path")
}
// Finally, whether we are animating or not, make the border layer show the new path.
// If we are animating, this will appear when the animation is finished.
// If we are not animating, this will appear immediately.
self.borderLayer.path = newPath
}
}
注意,無論是這些替代品的需要壓倒一切的viewWillTransitionToSize
或traitCollectionDidChange
。這些是更高層次的概念,可能會在設備輪換期間調用,但如果其他代碼更改視圖的大小則不會發生這種情況。最好使用簡單的UIView
級別的drawRect
或layoutSubviews
方法,因爲它們將始終有效。
不要求人們下載您的項目,找到相關的代碼並提供解決方案,您應該僅使用代碼的相關部分更新您的問題。 – rmaddy