【发布时间】:2018-10-27 18:44:30
【问题描述】:
我有一个需要完全以编程方式创建 UIView 的场景。此视图显示为视频源的叠加层,它包含 2 个 UILabel 作为子视图。
这些标签可以有不同的宽度和高度,所以我不想为 UIView 或标签创建一个固定的框架。
我已经用程序约束完成了这个,没有问题,但问题是移动手机时视图出现故障,我正在使用的框架建议不要使用自动布局,因为这个确切的问题.
我当前的代码:
-
我创建视图
func ar(_ arViewController: ARViewController, viewForAnnotation: ARAnnotation) -> ARAnnotationView { let annotationView = AnnotationView() //*this is the view, inherits from UIView annotationView.annotation = viewForAnnotation annotationView.delegate = self return annotationView } -
以及实际的视图代码
class AnnotationView: ARAnnotationView { var titleLabel: UILabel? var distanceLabel: UILabel! var delegate: AnnotationViewDelegate? override var annotation: ARAnnotation? { didSet { loadUI() } } override func didMoveToSuperview() { super.didMoveToSuperview() setupUI() } private func setupUI() { layer.cornerRadius = 5 layer.masksToBounds = true backgroundColor = .transparentWhite } private func loadUI() { titleLabel?.removeFromSuperview() distanceLabel?.removeFromSuperview() let label = UILabel() label.font = UIFont(name: "AvenirNext-Medium", size: 16.0) ?? UIFont.systemFont(ofSize: 14) label.numberOfLines = 2 label.textColor = UIColor.white self.titleLabel = label distanceLabel = UILabel() distanceLabel.textColor = .cbPPGreen distanceLabel.font = UIFont(name: "AvenirNext-Medium", size: 14.0) ?? UIFont.systemFont(ofSize: 12) distanceLabel.textAlignment = .center self.translatesAutoresizingMaskIntoConstraints = false label.translatesAutoresizingMaskIntoConstraints = false distanceLabel.translatesAutoresizingMaskIntoConstraints = false self.addSubview(label) self.addSubview(distanceLabel) if self.constraints.isEmpty { NSLayoutConstraint.activate([ NSLayoutConstraint(item: label, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1, constant: 5), NSLayoutConstraint(item: label, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1, constant: -5), NSLayoutConstraint(item: label, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0), NSLayoutConstraint(item: label, attribute: .bottom, relatedBy: .equal, toItem: distanceLabel, attribute: .top, multiplier: 1, constant: 0), NSLayoutConstraint(item: distanceLabel, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1, constant: 0), NSLayoutConstraint(item: distanceLabel, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1, constant: 0), NSLayoutConstraint(item: distanceLabel, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0), NSLayoutConstraint(item: distanceLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 15), ]) } if let annotation = annotation as? BikeStationAR { titleLabel?.text = annotation.address distanceLabel?.text = String(format: "%.2f km", annotation.distanceFromUser / 1000) } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { delegate?.didTouch(annotationView: self) } }
所以我现在的问题是:如何在不使用自动布局的情况下实现相同的行为?
编辑:这是https://streamable.com/s/4zusq/dvbgnb行为的视频
编辑 2:解决方案基于 Mahgol Fa 的回答并使用堆栈视图或垂直定位,以便不为各个标签设置框架。所以最终的实现是
private func loadUI() {
titleLabel?.removeFromSuperview()
distanceLabel?.removeFromSuperview()
let label = UILabel()
label.font = titleViewFont
label.numberOfLines = 0
label.textColor = UIColor.white
label.textAlignment = .center
self.titleLabel = label
distanceLabel = UILabel()
distanceLabel.textColor = .cbPPGreen
distanceLabel.font = subtitleViewFont
distanceLabel.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
distanceLabel.translatesAutoresizingMaskIntoConstraints = false
if let annotation = annotation as? BikeStationAR {
let title = annotation.address
let subtitle = String(format: "%.2f km", annotation.distanceFromUser / 1000)
let fontAttributeTitle = [NSAttributedString.Key.font: titleViewFont]
let titleSize = title.size(withAttributes: fontAttributeTitle)
let fontAttributeSubtitle = [NSAttributedString.Key.font: subtitleViewFont]
let subtitleSize = annotation.address.size(withAttributes: fontAttributeSubtitle)
titleLabel?.text = title
distanceLabel?.text = subtitle
let stackView = UIStackView(frame: CGRect(x: 0, y: 0, width: titleSize.width + 5, height: titleSize.height + subtitleSize.height + 5))
stackView.axis = .vertical
stackView.distribution = .fillProportionally
stackView.alignment = .fill
stackView.addArrangedSubview(titleLabel ?? UIView())
stackView.addArrangedSubview(distanceLabel)
frame = stackView.bounds
addSubview(stackView)
}
}
【问题讨论】:
-
你能展示一下它出现故障时的截图吗?
-
移动手机是什么意思?喜欢旋转?
-
我添加了一个视频。
标签: ios swift uiview autolayout