以编程方式创建基于子视图(标签)的UIView

时间:2018-10-27 18:44:30

标签: ios swift uiview autolayout

我有一个需要完全以编程方式创建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)
        }
    }

1 个答案:

答案 0 :(得分:1)

这样,您可以获取标签文字的宽度:

 awk 'NR>2{print $2}' file | 
 sort -t "+" -k3n -k2n |  
 awk '{a[NR]=$0} END{
  for (i=1;i<=length(a);i++) print a[i] }' 
 110x16+255+63 
 178x59+29+65 
 178x59+223+65 
 178x59+417+65 
 178x59+611+65 
 240x151+462+176  
 240x151+87+257 
 240x151+366+355  
 240x151+77+448  
 240x151+468+542 
 240x151+140+624 

然后:

let fontAttributes1= [NSAttributedStringKey.font: your declared font in your code]
   let size1 = (“your string” as String).size(withAttributes: fontAttributes1)
let fontAttributes2= [NSAttributedStringKey.font: your declared font in your code]
   let size2 = (“your string” as String).size(withAttributes: fontAttributes2)