gpt4 book ai didi

ios - 以编程方式创建的 UIView 的框架为 0

转载 作者:搜寻专家 更新时间:2023-11-01 06:55:33 24 4
gpt4 key购买 nike

设置布局后无法访问 uiview 的框架。框架和中心被指定为 0,0 点。

我还应该提一下,这个项目中没有 Storyboard。所有 View 和一切都以编程方式创建。

我已经以编程方式创建了一个 UIView resultView 并将其添加为 scrollView 中的 subview ,它也被添加为 view 的 subview ,然后在名为 setupLayout() 的方法中设置约束和 anchor 我在 viewDidLoad() 中调用 setupLayout() 并在该方法之后调用另一个名为 configureShapeLayer() 的方法。在 configureShapeLayer() 中,我尝试访问我的 View 中心:

let center = resultView.center // should give resultView's center but gives 0

然后通过使用这个中心值,我尝试添加两个 bezierPaths 以获得状态栏类型的 View 。但是由于此时 resultView 的中心没有更新,所以它看起来放错了地方。请看下图:

misplaced status bar layer

我还尝试在 loadView() 中调用 setupLayout() 然后在 viewDidLoad() 中调用 configureShapeLayer() > 但没有任何改变。

因此,我需要一种方法来确保在调用 configureShapeLayer() 之前已在我的 View 中设置所有 View 、所有约束和布局。但是我该怎么做呢?

我还尝试在 viewWillLayoutSubviews()viewDidLayoutSubviews() 方法中调用 configureShapeLayer() 但它使情况变得更糟,并且没有工作要么。

整个 View Controller 文件如下:首先声明 View ,然后将它们添加到 prepareUI() 中的 View 中,在 prepareUI() 的末尾,另一个方法 setupLayout() 被调用。完成布局设置后,从viewDidLoad可以看出,最后调用了configureShapeLayer()方法。

import UIKit

class TryViewController: UIViewController {

let score: CGFloat = 70

lazy var percentage: CGFloat = {
return score / 100
}()

// MARK: View Declarations
private let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.backgroundColor = .white
return scrollView
}()

private let iconImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
return imageView
}()

let scoreLayer = CAShapeLayer()
let trackLayer = CAShapeLayer()

let percentageLabel: UILabel = {
let label = UILabel()
label.text = ""
label.textAlignment = .center
label.font = TextStyle.systemFont(ofSize: 50.0)
return label
}()

// This one is the one should have status bar at center.
private let resultView: UIView = {
let view = UIView()
view.backgroundColor = .purple
return view
}()

override func viewDidLoad() {
super.viewDidLoad()
prepareUI()
configureShapeLayer()
}

private func prepareUI() {

resultView.addSubviews(views: percentageLabel)

scrollView.addSubviews(views: iconImageView,
resultView)

view.addSubviews(views: scrollView)
setupLayout()
}

private func setupLayout() {
scrollView.fillSuperview()
iconImageView.anchor(top: scrollView.topAnchor,
padding: .init(topPadding: 26.0))
iconImageView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 0.31).isActive = true
iconImageView.heightAnchor.constraint(equalTo: iconImageView.widthAnchor, multiplier: 0.67).isActive = true
iconImageView.anchorCenterXToSuperview()

//percentageLabel.frame = CGRect(x: 0, y: 0, width: 105, height: 60)
//percentageLabel.center = resultView.center

percentageLabel.anchorCenterXToSuperview()
percentageLabel.anchorCenterYToSuperview()

let resultViewTopConstraintRatio: CGFloat = 0.104
resultView.anchor(top: iconImageView.bottomAnchor,
padding: .init(topPadding: (view.frame.height * resultViewTopConstraintRatio)))

resultView.widthAnchor.constraint(equalTo: scrollView.widthAnchor, multiplier: 0.533).isActive = true
resultView.heightAnchor.constraint(equalTo: resultView.widthAnchor, multiplier: 1.0).isActive = true
resultView.anchorCenterXToSuperview()

configureShapeLayer()
}

private func configureShapeLayer() {
let endAngle = ((2 * percentage) * CGFloat.pi) - CGFloat.pi / 2

let center = resultView.center // should give resultView's center but gives 0

// Track Layer Part
let trackPath = UIBezierPath(arcCenter: center, radius: 50, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)

trackLayer.path = trackPath.cgPath
trackLayer.strokeColor = UIColor.lightGray.cgColor // to make different
trackLayer.lineWidth = 10
trackLayer.fillColor = UIColor.clear.cgColor
trackLayer.lineCap = .round

resultView.layer.addSublayer(trackLayer)

// Score Fill Part
let scorePath = UIBezierPath(arcCenter: center, radius: 50, startAngle: -CGFloat.pi / 2, endAngle: endAngle, clockwise: true)

scoreLayer.path = scorePath.cgPath
scoreLayer.strokeColor = UIColor.red.cgColor
scoreLayer.lineWidth = 10
scoreLayer.fillColor = UIColor.clear.cgColor
scoreLayer.lineCap = .round
scoreLayer.strokeEnd = 0

resultView.layer.addSublayer(scoreLayer)

}
}

最佳答案

创建自定义 View 会更好。这将允许您在 View 大小发生变化时“自动”更新您的贝塞尔曲线路径。

它还允许您将绘图代码与 Controller 代码分开。

这是一个简单的例子。它在“resultView”上方添加了一个按钮 - 每次点击它都会将百分比增加 5(为了演示,百分比从 5 开始):

//
// PCTViewController.swift
//
// Created by Don Mag on 12/6/18.
//

import UIKit

class MyResultView: UIView {

let scoreLayer = CAShapeLayer()
let trackLayer = CAShapeLayer()

var percentage = CGFloat(0.0) {
didSet {
self.percentageLabel.text = "\(Int(percentage * 100))%"
self.setNeedsLayout()
}
}

let percentageLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = ""
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 40.0)
return label
}()

override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}

func commonInit() -> Void {

layer.addSublayer(trackLayer)
layer.addSublayer(scoreLayer)

addSubview(percentageLabel)

NSLayoutConstraint.activate([
percentageLabel.centerXAnchor.constraint(equalTo: centerXAnchor),
percentageLabel.centerYAnchor.constraint(equalTo: centerYAnchor)
])

}

override func layoutSubviews() {
super.layoutSubviews()

let endAngle = ((2 * percentage) * CGFloat.pi) - CGFloat.pi / 2

trackLayer.frame = self.bounds
scoreLayer.frame = self.bounds

let centerPoint = CGPoint(x: self.bounds.width / 2.0, y: self.bounds.height / 2.0)

// Track Layer Part
let trackPath = UIBezierPath(arcCenter: centerPoint, radius: 50, startAngle: -CGFloat.pi / 2, endAngle: 2 * CGFloat.pi, clockwise: true)

trackLayer.path = trackPath.cgPath
trackLayer.strokeColor = UIColor.lightGray.cgColor // to make different
trackLayer.lineWidth = 10
trackLayer.fillColor = UIColor.clear.cgColor
// pre-Swift 4.2
trackLayer.lineCap = kCALineCapRound
// trackLayer.lineCap = .round

// Score Fill Part
let scorePath = UIBezierPath(arcCenter: centerPoint, radius: 50, startAngle: -CGFloat.pi / 2, endAngle: endAngle, clockwise: true)

scoreLayer.path = scorePath.cgPath
scoreLayer.strokeColor = UIColor.red.cgColor
scoreLayer.lineWidth = 10
scoreLayer.fillColor = UIColor.clear.cgColor
// pre-Swift 4.2
scoreLayer.lineCap = kCALineCapRound
// scoreLayer.lineCap = .round

}

}

class PCTViewController: UIViewController {

let resultView: MyResultView = {
let v = MyResultView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .purple
return v
}()

let btn: UIButton = {
let b = UIButton()
b.translatesAutoresizingMaskIntoConstraints = false
b.setTitle("Add 5 percent", for: .normal)
b.backgroundColor = .blue
return b
}()

var pct = 5

@objc func incrementPercent(_ sender: Any) {
pct += 5
resultView.percentage = CGFloat(pct) / 100.0
}

override func viewDidLoad() {
super.viewDidLoad()

view.addSubview(btn)
view.addSubview(resultView)

NSLayoutConstraint.activate([

btn.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20.0),
btn.centerXAnchor.constraint(equalTo: view.centerXAnchor),

resultView.widthAnchor.constraint(equalToConstant: 300.0),
resultView.heightAnchor.constraint(equalTo: resultView.widthAnchor),

resultView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
resultView.centerYAnchor.constraint(equalTo: view.centerYAnchor),

])

btn.addTarget(self, action: #selector(incrementPercent), for: .touchUpInside)

resultView.percentage = CGFloat(pct) / 100.0

}

}

结果:

enter image description here

关于ios - 以编程方式创建的 UIView 的框架为 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53655845/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com