如何以编程方式快速放置图层?

问题描述 投票:-1回答:3

我试图放置一个圆形进度条,但我一直在失败。我想我不了解框架,视图和界限的概念。我在堆栈溢出中发现了这篇文章,该文章确切地向我展示了如何构造圆形进度条。

但是,在帖子中,使用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)
ios swift uikit
3个回答
1
投票

边界是图层/视图在其本地坐标系中的坐标。框架是图层/视图在其父坐标系中的坐标。由于图层不参与自动布局,因此您应该实现UIViewController.viewDidLayoutSubviews(或UIView.layoutSubLayers)并将图层的frame设置为其上层视图的bounds(UIView的底层实际上是该视图的CoreGraphics版本)。

这也意味着您需要使用布局方法重新计算路径。如果那是昂贵的,那么请在单位空间中绘制路径,然后使用图层的变换将其缩放到视图的尺寸。


1
投票

帧是根据超级视图/超级图层坐标。如果您要说

circle.layer.addSublayer(progressCircle)

然后您必须根据progressCircleframebounds赋予circle.layer

一般来说,要使子层在其上层中居中,请说:

theSublayer.position = CGPoint(
    x:theSuperlayer.bounds.midX, 
    y:theSuperlayer.bounds.midY)

并在子视图中将子视图居中,您说:

theSubview.center = CGPoint(
    x:theSuperview.bounds.midX, 
    y:theSuperview.bounds.midY)

0
投票

解决方案是先添加子视图,然后在]创建整个循环进度视图。>

override func viewDidLayoutSubviews(){
     super.viewDidLayoutSubviews()
     // Add and position the circular progress bar and its layers here
}
© www.soinside.com 2019 - 2024. All rights reserved.