Sizing label with Autolayout

时间:2019-04-16 22:09:36

标签: ios swift autolayout uikit

Description of the issue

I have a label to the left side of a plot view in an iOS App. I have succeeded in rotatif the label 90 degrees, as pictured below, using the code copied in a following section :

enter image description here

However, as soon as I change the text to "Speed (Km/h):, the label becomes wider, as shown below :

enter image description here

Layout

There are no relevant contraints were set in interface builder. The only contraints set here are : - vertical centering of the label - plot view's right, top, and bottom edges stick to view's right, top, and bottom edges

The rest is set in code

enter image description here

Code

func setup(speedArray: [Float32]) {

    //Convert speed to Km/h from m/s
    let speedArrayKMH = speedArray.map({$0*3.6})

    //Draw Chart
    //This only styles the chart (colors, user interaction, etc...
    //no code in this fuction that affects layout)
    setupSpeedChart(speedArray: speedArrayKMH)

    //
    //  Customise speed label
    //
    //Label text
    chartTitleLabel.textAlignment = .center
    //Text color
    self.chartTitleLabel.textColor = BoxTextColor
    //Rotate
    chartTitleLabel.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi/2))
    //Constrain
    let C1 = NSLayoutConstraint(item: chartTitleLabel, attribute: .leadingMargin, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 0)
    let C2 = NSLayoutConstraint(item: chartTitleLabel, attribute: .trailingMargin, relatedBy: .equal, toItem: speedLineChart, attribute: .leading, multiplier: 1, constant: 0)

    NSLayoutConstraint.activate([C1, C2])

}

What I've tried

I've tried a number of construit and size combinations, including :

  • fixing the label's frame property (height and width)
  • adding a constraint for the label's width and height

nothing seems to work

Adding the following constraint for label width for example produces this :

let C3 = NSLayoutConstraint(item: chartTitleLabel, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 45)

enter image description here

2 个答案:

答案 0 :(得分:1)

there are few key thing missing first you forgot to use translateAutoReaizingMaskIntoConstraints

go to storyboard select your label go to inspector under label there is autoshrink set it to minimum font size set the size to 11

then do the following in view didload

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    myLabel.text = "speed in km"
    myLabel.textAlignment = .center
    myLabel.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi/2))
    myLabel.translatesAutoresizingMaskIntoConstraints = false
    let c1 = NSLayoutConstraint(item: myLabel, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200)
    let c2 = NSLayoutConstraint(item: myLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 60)

    let c3 = NSLayoutConstraint(item: myLabel, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: -60)
    let c4 = NSLayoutConstraint(item: myLabel, attribute: .centerY, relatedBy: .equal, toItem: myImageView, attribute: .centerY, multiplier: 1, constant: 0)

    NSLayoutConstraint.activate([c1, c2, c3, c4])

}

I have tried to update the text to new text with more character count than previous and I worked just fine

this is before changing text this is after changing the text

答案 1 :(得分:0)

问题出在苹果文档https://developer.apple.com/documentation/uikit/uiview/1622459-transform

中对transform的描述中。
  

在iOS 8.0和更高版本中,transform属性不会影响“自动布局”。自动布局会根据视图的未变形帧来计算视图的对齐矩形。

因此,当您更改标签的文本时,约束与 未转换的框架 相关。

解决方法是将标签嵌入“容器” UIView中,并将容器的 宽度 限制为 高度 ,以及标签的 宽度 高度

像这样设置您的xib(我使用对比色的背景色以使其更容易看到框架):

enter image description here

请注意,我已将容器视图的宽度和高度限制设置为80。编辑每个限制并将其设置为“占位符”:

enter image description here

我们将在代码中设置新的约束,因此这些约束将在构建时删除,但将满足IB的布局检查。

在自定义类的awakeFromNib()中,添加新的宽度和高度约束并应用旋转变换:

override func awakeFromNib() {
    super.awakeFromNib()

    // set HUGGING priority on title label to REQUIRED for both axis
    chartTitleLabel.setContentHuggingPriority(.required, for: .horizontal)
    chartTitleLabel.setContentHuggingPriority(.required, for: .vertical)

    NSLayoutConstraint.activate([

        // constrain title container view WIDTH equal to title label HEIGHT
        // set the constant to add padding on left and right of rotated title label
        // here it is set to 12, which gives 6-pts padding on each side
        chartTitleContainerView.widthAnchor.constraint(equalTo: chartTitleLabel.heightAnchor, constant: 12.0),

        // constrain title container view HEIGHT equal to title label WIDTH
        chartTitleContainerView.heightAnchor.constraint(equalTo: chartTitleLabel.widthAnchor, constant: 0.0),

        ])

    // rotate the title label
    chartTitleLabel.transform = CGAffineTransform(rotationAngle: CGFloat(-Double.pi/2))

    // un-comment after development
    //      chartTitleLabel.backgroundColor = .clear
    //      chartTitleContainerView.backgroundColor = .clear

}

现在,在您的setup()函数中(我假设您将“绘图视图”添加为子视图),为绘图视图添加约束:

func setup(speedArray: [Float32]) {

    //Convert speed to Km/h from m/s
    let speedArrayKMH = speedArray.map({$0*3.6})

    // assuming setupSpeedChart() creates speedLineChart view and adds it to self

    //Draw Chart
    //This only styles the chart (colors, user interaction, etc...
    //no code in this fuction that affects layout)
    setupSpeedChart(speedArray: speedArrayKMH)

    NSLayoutConstraint.activate([

        // constrain chart view LEADING to title container view TRAILING
        speedLineChart.leadingAnchor.constraint(equalTo: chartTitleContainerView.trailingAnchor, constant: 0.0),

        // constrain chart view top, bottom and trailing to self
        speedLineChart.topAnchor.constraint(equalTo: topAnchor, constant: 0.0),
        speedLineChart.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0.0),
        speedLineChart.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0.0),

        ])

}

这是结果:

enter image description here

并关闭“开发”颜色:

enter image description here

您现在可以更改标题标签的文本,并且该标签将保持垂直和水平居中,而无需更改水平尺寸/间距。