CAShapeLayer 形状可以在子视图中居中吗?
Can CAShapeLayer shapes center itself in a subView?
我创建了一个任意视图
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
view.addSubview(middleView)
然后我用UIBezierPath创建了一个圆;但是,当我将位置设置为 middleView.center 时,圆圈远离视图底部。可以设置子视图的中心位置吗?
let shapeLayer = CAShapeLayer()
let circlePath = UIBezierPath(
arcCenter: .zero,
radius: 100,
startAngle: CGFloat(0).toRadians(),
endAngle: CGFloat(360).toRadians(),
clockwise: true)
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
。视图的 center
是父视图的几何图形。换句话说,middleView.center
是相对于 view
,而不是 middleView
。但是你要添加 shapeLayer
作为 middleView.layer
的子层,这意味着 shapeLayer
需要一个 position
在 middleView
的几何结构中,而不是在 view
的几何。您需要将 shapeLayer.position
设置为 middleView.bounds
的中心:
shapeLayer.position = CGPoint(x: middleView.bounds.midX, y: middleView.bounds.midY)
其次,你没有说你在哪里做这一切。我猜你是在 viewDidLoad
中做的。但那还为时过早。在 viewDidLoad
中,从情节提要中加载的视图仍然具有情节提要中提供的框架,并且尚未针对当前设备的屏幕尺寸进行布局。所以在 viewDidLoad
中查看 frame
(或 bounds
或 center
)是一个坏主意,如果你不做一些事情来确保事情会被正确布置的话在布局阶段。通常您通过设置 autoresizingMask
或创建约束来做到这一点。示例:
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
或者constraints来控制shape的布局,在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
}
}
结果:
旋转到横向后:
我创建了一个任意视图
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
view.addSubview(middleView)
然后我用UIBezierPath创建了一个圆;但是,当我将位置设置为 middleView.center 时,圆圈远离视图底部。可以设置子视图的中心位置吗?
let shapeLayer = CAShapeLayer()
let circlePath = UIBezierPath(
arcCenter: .zero,
radius: 100,
startAngle: CGFloat(0).toRadians(),
endAngle: CGFloat(360).toRadians(),
clockwise: true)
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
。视图的 center
是父视图的几何图形。换句话说,middleView.center
是相对于 view
,而不是 middleView
。但是你要添加 shapeLayer
作为 middleView.layer
的子层,这意味着 shapeLayer
需要一个 position
在 middleView
的几何结构中,而不是在 view
的几何。您需要将 shapeLayer.position
设置为 middleView.bounds
的中心:
shapeLayer.position = CGPoint(x: middleView.bounds.midX, y: middleView.bounds.midY)
其次,你没有说你在哪里做这一切。我猜你是在 viewDidLoad
中做的。但那还为时过早。在 viewDidLoad
中,从情节提要中加载的视图仍然具有情节提要中提供的框架,并且尚未针对当前设备的屏幕尺寸进行布局。所以在 viewDidLoad
中查看 frame
(或 bounds
或 center
)是一个坏主意,如果你不做一些事情来确保事情会被正确布置的话在布局阶段。通常您通过设置 autoresizingMask
或创建约束来做到这一点。示例:
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
或者constraints来控制shape的布局,在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
}
}
结果:
旋转到横向后: