#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»:
Теперь вы можете изменить текст метки заголовка, и он останется центрированным по вертикали и горизонтали, без изменения размера / интервала по горизонтали.