Autolayout - собственный размер UIButton не включает в себя вставки заголовков
Если у меня есть UIButton, организованный с использованием автозапуска, его размер прекрасно настраивается, чтобы соответствовать его контенту.
Если я установил изображение как button.image
, размер экземпляра снова, похоже, учитывает это.
Однако, если я настраиваю кнопку titleEdgeInsets
кнопки, макет не учитывает это и вместо этого сокращает заголовок кнопки.
Как я могу гарантировать, что внутренняя ширина кнопки учитывает вставку?
![enter image description here]()
Edit:
Я использую следующее:
[self.backButton setTitleEdgeInsets:UIEdgeInsetsMake(0, 5, 0, 0)];
Цель состоит в том, чтобы добавить некоторое разделение между изображением и текстом.
Ответы
Ответ 1
Вы можете решить эту проблему без необходимости переопределять любые методы или устанавливать произвольное ограничение ширины. Вы можете сделать все это в Interface Builder следующим образом.
-
Внутренняя ширина кнопки получается из ширины заголовка плюс ширина значка плюс вставки левого и правого содержимого.
-
Если кнопка имеет как изображение, так и текст, они центрируются как группа, без пробелов между ними.
-
Если вы добавите левую вставку содержимого, ее вычислено относительно текста, а не значок "текст +".
-
Если вы устанавливаете вставку с отрицательным левым изображением, изображение вытягивается влево, но общая ширина кнопки не изменяется.
-
Если вы устанавливаете вставку с отрицательным левым изображением, фактический макет использует половину этого значения. Таким образом, чтобы получить вставку -20 точек влево, вы должны использовать значение вставки -40 точек в интерфейсе Builder.
Таким образом, вы создаете достаточно большую левую вставку для создания места как для желаемой левой вставки, так и для внутренней прокладки между значком и текстом, а затем переместите значок слева, удвоив количество отступов, которое вы хотите между значком и текст. Результатом является кнопка с равными вставками слева и справа, а также пара слов и значков, которые сосредоточены как группа, с определенным количеством дополнений между ними.
Некоторые примерные значения:
// Produces a button with the layout:
// |-20-icon-10-text-20-|
// AutoLayout intrinsic width works as you'd desire.
button.contentEdgeInsets = UIEdgeInsetsMake(10, 30, 10, 20)
button.imageEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0)
Ответ 2
Вы можете заставить это работать в Interface Builder (без написания кода), используя комбинацию отрицательных и позитивных вложений Title и Content.
![enter image description here]()
Обновить. В Xcode 7 есть ошибка, в которой вы не можете вводить отрицательные значения в поле Right
Inset, но вы можете использовать шаговый элемент управления рядом с ним для уменьшения значения. (Спасибо Stuart)
Выполняя это, вы добавите 8pt интервала между изображением и заголовком и увеличите внутреннюю ширину кнопки на ту же сумму. Вот так:
![enter image description here]()
Ответ 3
Почему бы не переопределить метод intrinsicContentSize
в UIView? Например:
- (CGSize) intrinsicContentSize
{
CGSize s = [super intrinsicContentSize];
return CGSizeMake(s.width + self.titleEdgeInsets.left + self.titleEdgeInsets.right,
s.height + self.titleEdgeInsets.top + self.titleEdgeInsets.bottom);
}
Это должно указывать системе автоопределения, что она должна увеличить размер кнопки, чтобы разрешить вставки и показать полный текст. Я не на своем компьютере, поэтому я не тестировал это.
Ответ 4
Вы не указали, как вы устанавливаете вставки, поэтому я предполагаю, что вы используете titleEdgeInsets, потому что я вижу тот же эффект, который вы получаете. Если я использую contentEdgeInsets, он работает правильно.
- (IBAction)ChangeTitle:(UIButton *)sender {
self.button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20);
[self.button setTitle:@"Long Long Title" forState:UIControlStateNormal];
}
Ответ 5
И для Swift это сработало:
extension UIButton {
override open var intrinsicContentSize: CGSize {
let intrinsicContentSize = super.intrinsicContentSize
let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom
return CGSize(width: adjustedWidth, height: adjustedHeight)
}
}
Любовь U Swift
Ответ 6
Эта ветка немного устарела, но я сам столкнулся с ней и смог решить ее с помощью отрицательной вставки. Например, подставьте желаемые значения отступа здесь:
UIButton* myButton = [[UIButton alloc] init];
// setup some autolayout constraints here
myButton.titleEdgeInsets = UIEdgeInsetsMake(-desiredBottomPadding,
-desiredRightPadding,
-desiredTopPadding,
-desiredLeftPadding);
В сочетании с правильными ограничениями автоматической разметки вы получаете кнопку автоматического изменения размера, которая содержит изображение и текст! Видно ниже с desiredLeftPadding
10.
![Button with image and short text]()
![Button with image and long text]()
Вы можете видеть, что фактический кадр кнопки не охватывает метку (поскольку метка смещена на 10 пунктов вправо, за пределы границ), но мы достигли 10 точек заполнения между текстом и изображением.
Ответ 7
Для Swift 3 на основе pegpeg answer:
extension UIButton {
override open var intrinsicContentSize: CGSize {
let intrinsicContentSize = super.intrinsicContentSize
let adjustedWidth = intrinsicContentSize.width + titleEdgeInsets.left + titleEdgeInsets.right
let adjustedHeight = intrinsicContentSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom
return CGSize(width: adjustedWidth, height: adjustedHeight)
}
}
Ответ 8
Все выше не работало для iOS 9 +, что я сделал:
- Добавьте ограничение ширины (для минимальной ширины, когда кнопка не имеет текста. Кнопка будет автоматически масштабироваться, если текст предоставлен)
- установить отношение к значению большего или равного
![введите описание изображения здесь]()
Теперь, чтобы добавить рамку вокруг кнопки, просто используйте метод:
button.contentEdgeInsets = UIEdgeInsetsMake(0,20,0,20);
Ответ 9
Я хотел добавить 5pt пробел между моей иконкой UIButton и ярлыком. Так я достиг этого:
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeCustom];
// more button config etc
infoButton.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 5);
infoButton.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 0, -5);
Способ, которым contentEdgeInsets, titleEdgeInsets и imageEdgeInsets соотносятся друг с другом, требует немного отдачи и принятия от каждой вставки. Поэтому, если вы добавите некоторые вставки в заголовок слева, вам нужно добавить отрицательную вставку справа и предоставить еще немного места (через положительную вставку) в правом правиле.
Добавив нужную вставку содержимого для соответствия сдвигу заглавных букв, мой текст не выходит за рамки кнопки.
Ответ 10
Опция также доступна в построителе интерфейса. См. Вставку. Я устанавливаю слева и справа на 3. Работает как шарм.
![Interface builder screenshot]()
Ответ 11
Решение, которое я использую, заключается в добавлении ограничения ширины на кнопку. Затем, где-то в инициализации, после того, как ваш текст установлен, обновите ограничение ширины следующим образом:
self.buttonWidthConstraint.constant = self.shareButton.intrinsicContentSize.width + 8;
Где 8 - какая бы ни была ваша вставка.
Ответ 12
Вызов sizeToFit() гарантирует, что contentEdgeInset вступит в силу
extension UIButton {
open override func draw(_ rect: CGRect) {
self.contentEdgeInsets = UIEdgeInsets(top: 10, left: 40, bottom: 10, right: 40)
self.sizeToFit()
}
}