Swift CAShapeLayer形状可以在子视图中居中吗?
我创建了一个任意视图Swift CAShapeLayer形状可以在子视图中居中吗?,swift,cashapelayer,caanimation,Swift,Cashapelayer,Caanimation,我创建了一个任意视图 让middleView=UIView( 帧:CGRect(x:0.0, y:view.frame.height/4, 宽度:view.frame.width, 高度:视图。框架。高度/4) middleView.backgroundColor=UIColor.blue view.addSubview(middleView) 然后我用UIBezierPath创建了一个圆;但是,当我将位置设置为middleView.center时,圆圈远离视图底部。可以设置子视图中心的位置吗
让middleView=UIView(
帧:CGRect(x:0.0,
y:view.frame.height/4,
宽度:view.frame.width,
高度:视图。框架。高度/4)
middleView.backgroundColor=UIColor.blue
view.addSubview(middleView)
然后我用UIBezierPath创建了一个圆;但是,当我将位置设置为middleView.center时,圆圈远离视图底部。可以设置子视图中心的位置吗
let shapeLayer=CAShapeLayer()
设circlePath=UIBezierPath(
弧中心:。零,
半径:100,
startAngle:CGFloat(0).toRadians(),
端角:CGFloat(360).toRadians(),
顺时针:正确)
shapeLayer.path=circlePath.cgPath
shapeLayer.strokeColor=UIColor.purple.cgColor
shapeLayer.fillColor=UIColor.clear.cgColor
shapeLayer.position=middleView.center
middleView.layer.addSublayer(shapeLayer)
如何在该视图中使该圆居中?您有两个问题
首先,您要设置shapeLayer.position=middleView.center
。视图的中心是superview的几何体。换句话说,middleView.center
是相对于view
,而不是相对于middleView
。但随后您将shapeLayer
添加为middleView.layer
的子层,这意味着shapeLayer
需要一个位置,该位置位于middleView
的几何体中,而不是视图的几何体中。您需要将shapeLayer.position
设置为middleView.bounds的中心:
shapeLayer.position = CGPoint(x: middleView.bounds.midX, y: middleView.bounds.midY)
第二,你没有说你在哪里做这些。我猜你是在viewDidLoad
中完成的。但这还为时过早。在viewDidLoad
中,从故事板加载的视图仍然具有故事板中给出的帧,并且尚未针对当前设备的屏幕大小进行布局。因此,如果在布局阶段没有采取措施确保正确布局,那么在viewdiload
中查看frame
(或bounds
或center
)是个坏主意。通常,您可以通过设置自动调整大小任务
或创建约束来实现这一点。例如:
let middleView = UIView(
frame: CGRect(x: 0.0,
y: view.frame.height/4,
width: view.frame.width,
height: view.frame.height/4))
middleView.backgroundColor = UIColor.blue
middleView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleTopMargin, .flexibleBottomMargin]
view.addSubview(middleView)
但是,shapeLayer
不属于视图,因此它没有autoresizingMask
,并且不能被约束。你必须用代码来描述它。可以这样做,但最好只使用视图来管理形状层。这样,您可以使用autoresizingMask
或约束来控制形状的布局,并且可以在viewDidLoad
中进行设置
let circleView = CircleView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
circleView.center = CGPoint(x: middleView.bounds.midX, y: middleView.bounds.midY)
circleView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin, .flexibleBottomMargin]
circleView.shapeLayer.strokeColor = UIColor.purple.cgColor
circleView.shapeLayer.fillColor = nil
middleView.addSubview(circleView)
...
class CircleView: UIView {
override class var layerClass: AnyClass { return CAShapeLayer.self }
var shapeLayer: CAShapeLayer { return layer as! CAShapeLayer }
override func layoutSubviews() {
super.layoutSubviews()
shapeLayer.path = UIBezierPath(ovalIn: bounds).cgPath
}
}
结果:
旋转到横向后:
您有两个问题
首先,您要设置shapeLayer.position=middleView.center
。视图的中心是superview的几何体。换句话说,middleView.center
是相对于view
,而不是相对于middleView
。但随后您将shapeLayer
添加为middleView.layer
的子层,这意味着shapeLayer
需要一个位置,该位置位于middleView
的几何体中,而不是视图的几何体中。您需要将shapeLayer.position
设置为middleView.bounds的中心:
shapeLayer.position = CGPoint(x: middleView.bounds.midX, y: middleView.bounds.midY)
第二,你没有说你在哪里做这些。我猜你是在viewDidLoad
中完成的。但这还为时过早。在viewDidLoad
中,从故事板加载的视图仍然具有故事板中给出的帧,并且尚未针对当前设备的屏幕大小进行布局。因此,如果在布局阶段没有采取措施确保正确布局,那么在viewdiload
中查看frame
(或bounds
或center
)是个坏主意。通常,您可以通过设置自动调整大小任务
或创建约束来实现这一点。例如:
let middleView = UIView(
frame: CGRect(x: 0.0,
y: view.frame.height/4,
width: view.frame.width,
height: view.frame.height/4))
middleView.backgroundColor = UIColor.blue
middleView.autoresizingMask = [.flexibleWidth, .flexibleHeight, .flexibleTopMargin, .flexibleBottomMargin]
view.addSubview(middleView)
但是,shapeLayer
不属于视图,因此它没有autoresizingMask
,并且不能被约束。你必须用代码来描述它。可以这样做,但最好只使用视图来管理形状层。这样,您可以使用autoresizingMask
或约束来控制形状的布局,并且可以在viewDidLoad
中进行设置
let circleView = CircleView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
circleView.center = CGPoint(x: middleView.bounds.midX, y: middleView.bounds.midY)
circleView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin, .flexibleBottomMargin]
circleView.shapeLayer.strokeColor = UIColor.purple.cgColor
circleView.shapeLayer.fillColor = nil
middleView.addSubview(circleView)
...
class CircleView: UIView {
override class var layerClass: AnyClass { return CAShapeLayer.self }
var shapeLayer: CAShapeLayer { return layer as! CAShapeLayer }
override func layoutSubviews() {
super.layoutSubviews()
shapeLayer.path = UIBezierPath(ovalIn: bounds).cgPath
}
}
结果:
旋转到横向后:
谢谢!这是非常有见地的。一个问题:我可以为自动布局约束切换出circleView.autoresizingMask=[…]
?它们执行相同的任务吗?是的,如果您记得设置circleView.translatesAutoResizezingMacSkinToConstraints=false
,您可以使用约束来布局circleView
,我很困惑CGRect.x
和CGRect.y
中的0
是如何允许圆居中的,这并不重要,因为我在下一行设置了circleView.center
。谢谢!这是非常有见地的。一个问题:我可以为自动布局约束切换出circleView.autoresizingMask=[…]
?它们执行相同的任务吗?是的,如果您记得设置circleView.translatesAutoResizezingMacSkinToConstraints=false
,您可以使用约束来布局circleView
,我很困惑CGRect.x
和CGRect.y
中的0
是如何允许圆居中的,这并不重要,因为我在下一行设置了circleView.center
。