Метка размера с автозаполнением

#ios #swift #autolayout #uikit

#iOS #swift #автозаполнение #uikit

Вопрос:

Описание проблемы

У меня есть метка в левой части графика в приложении iOS. Мне удалось повернуть метку на 90 градусов, как показано на рисунке ниже, используя код, скопированный в следующем разделе :

введите описание изображения здесь

Однако, как только я меняю текст на «Скорость (км / ч):, метка становится шире, как показано ниже :

введите описание изображения здесь

Макет

В конструкторе интерфейсов не было установлено соответствующих ограничений. Единственными установленными здесь ограничениями являются: — вертикальное центрирование метки — правый, верхний и нижний края представления графика привязаны к правому, верхнему и нижнему краям представления

Остальное задается в коде

введите описание изображения здесь

Код

 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])

}
 

Что я пробовал

Я перепробовал несколько комбинаций конструкций и размеров, в том числе :

  • исправление свойства рамки метки (высота и ширина)
  • добавление ограничения для ширины и высоты метки

кажется, ничего не работает

Например, добавление следующего ограничения для ширины метки приводит к следующему :

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

введите описание изображения здесь

Комментарии:

1. Ваши изображения просто немного сбивают с толку… является chartTitleLabel ли подвидом speedLineChart ? Это выглядит так на изображении вашего xib, но ваш код ограничивает chartTitleLabel конечное значение до speedLineChart начального?

Ответ №1:

сначала не хватает нескольких ключевых моментов, которые вы забыли использовать translateAutoReaizingMaskIntoConstraints

перейдите в раскадровку выберите свой ярлык перейдите в инспектор под ярлыком есть автоусадка установите для него минимальный размер шрифта установите размер на 11

затем выполните следующие действия в представлении 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])

}
 

Я попытался обновить текст до нового текста с большим количеством символов, чем в предыдущем, и у меня все получилось просто отлично

это перед изменением текста
это после изменения текста

Комментарии:

1. Привет, спасибо за ответ! Это не изменилось (пробовал оба изменения вместе и по отдельности). Я поставил chartTitleLabel.translatesAutoresizingMaskIntoConstraints = false перед ограничениями, но не в поле зрения загружал (потому что в подклассе UIView)

Ответ №2:

Проблема заключается в этой части описания transform в документах Apple: https://developer.apple.com/documentation/uikit/uiview/1622459-transform

В iOS 8.0 и более поздних версиях свойство transform не влияет на автоматическую компоновку. Автоматическая компоновка вычисляет прямоугольник выравнивания вида на основе его нетрансформированного фрейма.

Итак, когда вы меняете текст метки, ваши ограничения связаны с нетрансформированным фреймом.

Исправление заключается в том, чтобы встроить метку в «контейнер» UIView и ограничить ширину контейнера высотой метки, а высоту шириной метки.

Настройте свой xib следующим образом (я использую контрастные цвета фона, чтобы было легче видеть рамки):

введите описание изображения здесь

Обратите внимание, что я установил ограничения по ширине и высоте контейнера, равные 80. Отредактируйте каждое из этих ограничений и установите их как «Заполнители»:

введите описание изображения здесь

Мы будем устанавливать новые ограничения в коде, поэтому они будут удалены во время сборки, но будут соответствовать проверке макета 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),

        ])

}
 

Это результат:

введите описание изображения здесь

и с отключенными цветами «dev»:

введите описание изображения здесь

Теперь вы можете изменить текст метки заголовка, и он останется центрированным по вертикали и горизонтали, без изменения размера / интервала по горизонтали.