我试图放置一个圆形进度条,但我一直在失败。我想我不了解框架,视图和界限的概念。我在堆栈溢出中发现了这篇文章,该文章确切地向我展示了如何构造圆形进度条。
但是,在帖子中,使用CGRect(x:100,y:100,宽度:100,高度:100)将circleView创建为UIView]
就我而言,手动设置x和y坐标是一个很大的问题。因此circleView必须位于其父视图的中心。
这是我的视图层次结构:
view -> view2ForHomeController -> middleView -> circleView
因此,所有内容均使用自动布局进行定位。问题出在这里:circleView添加正确,并且将其自身定位在我指定的x和y值处,但是如何指定MiddleView中心的x和y值。我尝试了以下操作,但中心值返回为0.0、0.0。
self.view.addSubview(self.view2ForHomeController)
self.view2ForHomeController.fillSuperview()
let xPosition = self.view2ForHomeController.middleView.frame.midX
let yPostion = self.view2ForHomeController.middleView.frame.midY
print(xPosition) // ------- PRINTS ZERO
print(yPostion) // ------- PRINTS ZERO
let circle = UIView(frame: CGRect(x: xPosition, y: yPostion, width: 100, height: 100))
circle.backgroundColor = UIColor.green
self.view2ForHomeController.middleView.addSubview(circle)
var progressCircle = CAShapeLayer()
progressCircle.frame = self.view.bounds
let lineWidth: CGFloat = 10
let rectFofOval = CGRect(x: lineWidth / 2, y: lineWidth / 2, width: circle.bounds.width - lineWidth, height: circle.bounds.height - lineWidth)
let circlePath = UIBezierPath(ovalIn: rectFofOval)
progressCircle = CAShapeLayer ()
progressCircle.path = circlePath.cgPath
progressCircle.strokeColor = UIColor.white.cgColor
progressCircle.fillColor = UIColor.clear.cgColor
progressCircle.lineWidth = 10.0
progressCircle.frame = self.view.bounds
progressCircle.lineCap = CAShapeLayerLineCap(rawValue: "round")
circle.layer.addSublayer(progressCircle)
circle.transform = circle.transform.rotated(by: CGFloat.pi/2)
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.toValue = 1.1
animation.duration = 1
animation.repeatCount = MAXFLOAT
animation.fillMode = CAMediaTimingFillMode.forwards
animation.isRemovedOnCompletion = false
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn)
progressCircle.add(animation, forKey: nil)
边界是图层/视图在其本地坐标系中的坐标。框架是图层/视图在其父坐标系中的坐标。由于图层不参与自动布局,因此您应该实现UIViewController.viewDidLayoutSubviews
(或UIView.layoutSubLayers
)并将图层的frame
设置为其上层视图的bounds
(UIView的底层实际上是该视图的CoreGraphics版本)。
这也意味着您需要使用布局方法重新计算路径。如果那是昂贵的,那么请在单位空间中绘制路径,然后使用图层的变换将其缩放到视图的尺寸。
帧是根据超级视图/超级图层坐标。如果您要说
circle.layer.addSublayer(progressCircle)
然后您必须根据progressCircle
的frame
为bounds
赋予circle.layer
。
一般来说,要使子层在其上层中居中,请说:
theSublayer.position = CGPoint(
x:theSuperlayer.bounds.midX,
y:theSuperlayer.bounds.midY)
并在子视图中将子视图居中,您说:
theSubview.center = CGPoint(
x:theSuperview.bounds.midX,
y:theSuperview.bounds.midY)
解决方案是先添加子视图,然后在]创建整个循环进度视图。>
override func viewDidLayoutSubviews(){
super.viewDidLayoutSubviews()
// Add and position the circular progress bar and its layers here
}