UIButton, который изменяет размер, чтобы соответствовать его titleLabel
У меня есть UIButton, который я добавляю к представлению контроллера вида в раскадровке. Я добавляю ограничения центрирования, чтобы расположить его и удержать ограничения пространства, чтобы ограничить его ширину. В коде я добавляю:
self.button.titleLabel.numberOfLines = 0;
self.button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[self.button setTitle:@"A real real real real real real real real long long name." forState:UIControlStateNormal];
self.button.backgroundColor = [UIColor redColor];
self.button.titleLabel.backgroundColor = [UIColor blueColor];
Результат показан ниже:
![enter image description here]()
Я хочу, чтобы кнопка меняла свой контент. Как я могу это сделать?
Я пробовал
[self.button sizeToFit];
и я попытался установить приоритеты ограничений автоопределения содержимого и ограничения на сжатие.
Я также попытался явно установить параметры contentEdgeInsets и titleEdgeInsets в UIEdgeInsetsZero и вызвать invalidateIntrinsicContentsize.
Я также заметил, что если я помещаю символы новой строки в строку заголовка, кнопка, похоже, изменит размер, чтобы соответствовать его контенту.
Я запускаю Xcode 6 и iOS 8 на симуляторе iphone 6.
Ответы
Ответ 1
Я получил это, чтобы работать, но вы должны использовать настраиваемую кнопку, а не тип системы. Дайте кнопке ограничения ширины и высоты и сделайте IBOutlet для ограничения высоты (heightCon в моем коде), чтобы вы могли настроить его в коде.
- (void)viewDidLoad {
[super viewDidLoad];
self.button.titleLabel.numberOfLines = 0;
self.button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[self.button setTitle:@"A real real real real real real real real long long name." forState:UIControlStateNormal];
[self.button addTarget:self action:@selector(doStuff:) forControlEvents:UIControlEventTouchUpInside];
self.button.backgroundColor = [UIColor redColor];
self.button.titleLabel.backgroundColor = [UIColor blueColor];
[self.button layoutIfNeeded]; // need this to update the button titleLabel size
self.heightCon.constant = self.button.titleLabel.frame.size.height;
}
После редактирования:
Я обнаружил, что вы можете сделать это проще, и с помощью системной кнопки, если вы создаете подкласс и используете этот код,
@implementation RDButton
-(CGSize)intrinsicContentSize {
return CGSizeMake(self.frame.size.width, self.titleLabel.frame.size.height);
}
Вызывается переопределенный метод intrinsicContentSize при установке заголовка. В этом случае вы не должны устанавливать ограничение по высоте.
Ответ 2
Swift 3 версия ответ Кубба:
class ResizableButton: UIButton {
override var intrinsicContentSize: CGSize {
let labelSize = titleLabel?.sizeThatFits(CGSize(width: frame.width, height: .greatestFiniteMagnitude)) ?? .zero
let desiredButtonSize = CGSize(width: labelSize.width + titleEdgeInsets.left + titleEdgeInsets.right, height: labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom)
return desiredButtonSize
}
}
Ответ 3
У вас такая же проблема. Это происходит, только если UIButton
titleLabel
имеет более одной строки. Это ошибка в UIKit?
My Swift:
class ResizableButton: UIButton {
override func intrinsicContentSize() -> CGSize
{
let labelSize = titleLabel?.sizeThatFits(CGSizeMake(self.frame.size.width, CGFloat.max)) ?? CGSizeZero
let desiredButtonSize = CGSizeMake(labelSize.width + titleEdgeInsets.left + titleEdgeInsets.right, labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom)
return desiredButtonSize
}
Ответ 4
Я далеко от компьютера, поэтому я не могу добавить код прямо сейчас, но я нашел обходное решение этого раньше.
Что вы можете сделать, это создать UILabel
и добавить UITapGestureRecognizer
к метке. Сделайте все, что хотите для действия кнопки, обработав событие крана. А также убедитесь, что вы активируете взаимодействие пользователя с UILabel
.
Теперь эта метка будет действовать как кнопка автоматического изменения размера.
Ответ 5
Я боролся с этим некоторое время и в конечном итоге сделал его работу путем подкласса UIButton и добавления этих двух функций
class GoalsButton: UIButton {
override var intrinsicContentSize: CGSize {
return self.titleLabel!.intrinsicContentSize
}
// Whever the button is changed or needs to layout subviews,
override func layoutSubviews() {
super.layoutSubviews()
titleLabel?.preferredMaxLayoutWidth = self.titleLabel!.frame.size.width
}
}
Ответ 6
Я бы предложил рассчитать ширину текста и рассчитать кадр самостоятельно. Это все равно не сложно, сначала получите ширину текста:
[NSString sizeWithFont:font];
Сделайте операцию mod, и вы легко узнаете количество строк для текста.
Обратите внимание, что этот метод предназначен для pre iOS7, для iOS 7 и после того, как вы захотите попробовать
[NSString sizeWithAttributes:aDictionary];
Ответ 7
[self.button sizeToFit] должен работать, если ваш автозапуск отключен. Если вам нужно использовать автозапуск, более подходящими являются другие предложения (расчет ширины линии) и т.д.
Ответ 8
У меня была такая же проблема с UIButton
с многострочным текстом, и у него также было изображение. Я использовал sizeThatFits:
для вычисления размера, но он рассчитал неправильную высоту.
Я не сделал это UIButtonTypeCustom
, вместо этого я вызвал sizeThatFits:
на кнопке titleLabel
с размером с меньшей шириной (из-за изображения в кнопке):
CGSize buttonSize = [button sizeThatFits:CGSizeMake(maxWidth, maxHeight)];
CGSize labelSize = [button.titleLabel sizeThatFits:CGSizeMake(maxWidth - offset, maxHeight)]; // offset for image
buttonSize.height = labelSize.height;
buttonFrame.size = buttonSize;
И затем я использовал высоту от этого размера, чтобы правильно установить рамку кнопки, и она РАБОТАЛА:)
Возможно, у них есть ошибка во внутреннем размере UIButton
.
Ответ 9
Переопределить intrinsicContentSize - (CGSize) в пользовательской UIButton, как указано ниже.
Цель - C:
-(CGSize)intrinsicContentSize {
CGSize titleLabelIntrinsicSize = [self.titleLabel intrinsicContentSize];
return CGSizeMake(titleLabelIntrinsicSize.width + self.contentEdgeInsets.left + self.contentEdgeInsets.right, titleLabelIntrinsicSize.height + self.contentEdgeInsets.top + self.contentEdgeInsets.bottom);
}
Swfit:
override var intrinsicContentSize: CGSize {
get {
if let thisSize = self.titleLabel?.intrinsicContentSize {
return CGSize(width: thisSize.width + self.contentEdgeInsets.left + self.contentEdgeInsets.right, height: thisSize.height + self.contentEdgeInsets.top + self.contentEdgeInsets.bottom)
}
return super.intrinsicContentSize
}
}
Ответ 10
class SFResizableButton: UIButton {
override var intrinsicContentSize: CGSize {
get {
var labelSize = CGSize.zero
if let text = titleLabel?.text, let font = titleLabel?.font {
labelSize.width = text.width(constrained: .greatestFiniteMagnitude, font: font)
} else if let att = titleLabel?.attributedText {
labelSize.width = att.width(constrained: .greatestFiniteMagnitude)
}
if let imageView = imageView {
labelSize.width = labelSize.width + imageView.frame.width
}
let desiredButtonSize = CGSize(width: ceil(labelSize.width) + titleEdgeInsets.left + titleEdgeInsets.right + imageEdgeInsets.left + imageEdgeInsets.right, height: labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom + imageEdgeInsets.top + imageEdgeInsets.bottom)
return desiredButtonSize
}
}
}
extesion String {
func width(constrained height: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
let boundingBox = (self as NSString).boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return boundingBox.width
}
}
extension NSAttributedString {
func width(constrained height: CGFloat) -> CGFloat {
let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
let boundingBox = boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, context: nil)
return boundingBox.width
}
}