Не удалось получить UIView sizeToFit, чтобы сделать что-либо значимое
Когда я добавляю subview к UIView
или когда я изменяю размер существующего subview, я бы ожидал, что [view sizeToFit]
и [view sizeThatFits]
будут отражать это изменение. Однако, мой опыт заключается в том, что sizeToFit
ничего не делает, а sizeThatFits
возвращает одно и то же значение до и после изменения.
В моем тестовом проекте есть одно представление, содержащее одну кнопку. Нажатие кнопки добавляет еще одну кнопку в представление, а затем вызывает sizeToFit
на содержащем представлении. Границы представления сбрасываются на консоль до и после добавления subview.
- (void) logSizes {
NSLog(@"theView.bounds: %@", NSStringFromCGRect(theView.bounds));
NSLog(@"theView.sizeThatFits: %@", NSStringFromCGSize([theView sizeThatFits:CGSizeZero]));
}
- (void) buttonTouched {
[self logSizes];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.frame = CGRectMake(10.0f, 100.0f, 400.0f, 600.0f);
[theView addSubview:btn];
[theView sizeToFit];
[self performSelector:@selector(logSizes) withObject:nil afterDelay:1.0];
}
И результат:
2010-10-15 15:40:42.359 SizeToFit[14953:207] theView.bounds: {{0, 0}, {322, 240}}
2010-10-15 15:40:42.387 SizeToFit[14953:207] theView.sizeThatFits: {322, 240}
2010-10-15 15:40:43.389 SizeToFit[14953:207] theView.bounds: {{0, 0}, {322, 240}}
2010-10-15 15:40:43.391 SizeToFit[14953:207] theView.sizeThatFits: {322, 240}
Мне что-то не хватает.
Спасибо.
Ответы
Ответ 1
Документация довольно понятна. -sizeToFit
довольно много вызовов -sizeThatFits:
(возможно, с текущим размером представления в качестве аргумента), а реализация по умолчанию -sizeThatFits:
почти ничего (он просто возвращает свой аргумент).
Некоторые подклассы UIView переопределяют -sizeThatFits:
, чтобы сделать что-то более полезное (например, UILabel). Если вам нужны другие функции (например, изменение размера представления в соответствии с его подзонами), вы должны подклассифицировать UIView и переопределить -sizeThatFits:
.
Ответ 2
Если вы не будете переопределять UIView, вы можете просто использовать расширение.
Swift:
extension UIView {
func sizeToFitCustom () {
var size = CGSize(width: 0, height: 0)
for view in self.subviews {
let frame = view.frame
let newW = frame.origin.x + frame.width
let newH = frame.origin.y + frame.height
if newW > size.width {
size.width = newW
}
if newH > size.height {
size.height = newH
}
}
self.frame.size = size
}
}
Тот же код, но в 3 раза быстрее:
extension UIView {
final func sizeToFitCustom() {
var w: CGFloat = 0,
h: CGFloat = 0
for view in subviews {
if view.frame.origin.x + view.frame.width > w { w = view.frame.origin.x + view.frame.width }
if view.frame.origin.y + view.frame.height > h { h = view.frame.origin.y + view.frame.height }
}
frame.size = CGSize(width: w, height: h)
}
}
Ответ 3
Вы можете сделать что-то подобное, используя только IB (xcode 4.5):
- Нажмите
UIView
- в Инспекторе размеров перетащите
content hugging
в 1 (как по горизонтали, так и по вертикали)
- перетащите
compression resistance
в 1000 (для обоих)
- под UIView
constraints
нажмите Width
и измените priority
на 250
- Сделайте то же самое для Height
- Вы можете использовать
UIView
inset
для управления дополнением для левого/правого/верхнего/нижнего
Ответ 4
self.errorMessageLabel.text = someNewMessage;
// We don't know how long the given error message might be, so let resize the label + containing view accordingly
CGFloat heightBeforeResize = self.errorMessageLabel.frame.size.height;
[self.errorMessageLabel sizeToFit];
CGFloat differenceInHeightAfterResize = self.errorMessageLabel.frame.size.height - heightBeforeResize;
self.errorViewHeightContstraint.constant = kErrorViewHeightConstraintConstant + differenceInHeightAfterResize;
Это сработало для меня.