UIButton: как центрировать изображение и текст с помощью imageEdgeInsets и titleEdgeInsets?
Если я помещу в изображение только изображение и установлю imageEdgeInsets ближе к верху, изображение останется центрированным, и все будет работать как положено:
[button setImage:image forState:UIControlStateNormal];
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, 0.0)];
Если я помещу только текст в кнопку и установлю titleEdgeInsets ближе к основанию, текст останется центрированным, и все будет работать как положено:
[button setTitle:title forState:UIControlStateNormal];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, -30, 0.0)];
Но, если я соединю 4 строки, текст будет мешать изображению, и оба потеряли выравнивание по центру.
Все мои изображения имеют ширину 30 пикселей, и если я добавлю 30 в левый параметр UIEdgeInsetMake для setTitleEdgeInsets, текст снова будет центрирован. Проблема в том, что изображение никогда не центрируется, потому что кажется, что оно зависит от размера button.titleLabel. Я уже пробовал много вычислений с размером кнопки, размером изображения, размером titleLabel и никогда не получал идеальное центрирование.
У кого-то уже была такая же проблема?
Ответы
Ответ 1
Для чего это стоит, здесь общее решение для размещения изображения по центру над текстом без использования каких-либо магических чисел. Обратите внимание, что следующий код устарел, и вам, вероятно, следует использовать одну из обновленных версий ниже:
// the space between the image and text
CGFloat spacing = 6.0;
// lower the text and push it left so it appears centered
// below the image
CGSize imageSize = button.imageView.frame.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
// raise the image and push it right so it appears centered
// above the text
CGSize titleSize = button.titleLabel.frame.size;
button.imageEdgeInsets = UIEdgeInsetsMake(
- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
Следующая версия содержит изменения для поддержки iOS 7+, которые были рекомендованы в комментариях ниже. Я сам не тестировал этот код, поэтому не уверен, насколько хорошо он работает и не сломается ли, если используется в предыдущих версиях iOS.
// the space between the image and text
CGFloat spacing = 6.0;
// lower the text and push it left so it appears centered
// below the image
CGSize imageSize = button.imageView.image.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
// raise the image and push it right so it appears centered
// above the text
CGSize titleSize = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}];
button.imageEdgeInsets = UIEdgeInsetsMake(
- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
// increase the content height to avoid clipping
CGFloat edgeOffset = fabsf(titleSize.height - imageSize.height) / 2.0;
button.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0);
Swift 5.0 версия
extension UIButton {
func alignVertical(spacing: CGFloat = 6.0) {
guard let imageSize = imageView?.image?.size,
let text = titleLabel?.text,
let font = titleLabel?.font
else { return }
titleEdgeInsets = UIEdgeInsets(
top: 0.0,
left: -imageSize.width,
bottom: -(imageSize.height + spacing),
right: 0.0
)
let titleSize = text.size(withAttributes: [.font: font])
imageEdgeInsets = UIEdgeInsets(
top: -(titleSize.height + spacing),
left: 0.0,
bottom: 0.0, right: -titleSize.width
)
let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0
contentEdgeInsets = UIEdgeInsets(
top: edgeOffset,
left: 0.0,
bottom: edgeOffset,
right: 0.0
)
}
}
Ответ 2
Найден как.
Сначала настройте текст titleLabel
(из-за стилей, т. titleLabel
Полужирный, курсив и т.д.). Затем используйте setTitleEdgeInsets
учитывая ширину вашего изображения:
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont boldSystemFontOfSize:10.0]];
// Left inset is the negative of image width.
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, -image.size.width, -25.0, 0.0)];
После этого используйте setTitleEdgeInsets
учитывая ширину границ текста:
[button setImage:image forState:UIControlStateNormal];
// Right inset is the negative of text bounds width.
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, -button.titleLabel.bounds.size.width)];
Теперь изображение и текст будут центрированы (в этом примере изображение появляется над текстом).
Приветствия.
Ответ 3
Вы можете сделать это с помощью этого расширения Swift, которое было частично основано на ответе Джесси Кроссен:
extension UIButton {
func centerLabelVerticallyWithPadding(spacing:CGFloat) {
// update positioning of image and title
let imageSize = self.imageView.frame.size
self.titleEdgeInsets = UIEdgeInsets(top:0,
left:-imageSize.width,
bottom:-(imageSize.height + spacing),
right:0)
let titleSize = self.titleLabel.frame.size
self.imageEdgeInsets = UIEdgeInsets(top:-(titleSize.height + spacing),
left:0,
bottom: 0,
right:-titleSize.width)
// reset contentInset, so intrinsicContentSize() is still accurate
let trueContentSize = CGRectUnion(self.titleLabel.frame, self.imageView.frame).size
let oldContentSize = self.intrinsicContentSize()
let heightDelta = trueContentSize.height - oldContentSize.height
let widthDelta = trueContentSize.width - oldContentSize.width
self.contentEdgeInsets = UIEdgeInsets(top:heightDelta/2.0,
left:widthDelta/2.0,
bottom:heightDelta/2.0,
right:widthDelta/2.0)
}
}
Это определяет функцию centerLabelVerticallyWithPadding
, которая правильно устанавливает надписи заголовка и изображения.
Он также устанавливает contentEdgeInsets, который, по моему мнению, необходим, чтобы гарантировать, что intrinsicContentSize
работает корректно, что должно было бы использовать Auto Layout.
Я считаю, что все решения, подклассы UIButton являются технически незаконными, поскольку вы не должны подклассифицировать элементы управления UIKit. То есть, теоретически они могут ломаться в будущих выпусках.
Ответ 4
Изменить: Обновлено для Swift 3
Если вы ищете быстрое решение ответа Джесси Кроссена, вы можете добавить это в подкласс UIButton:
override func layoutSubviews() {
let spacing: CGFloat = 6.0
// lower the text and push it left so it appears centered
// below the image
var titleEdgeInsets = UIEdgeInsets.zero
if let image = self.imageView?.image {
titleEdgeInsets.left = -image.size.width
titleEdgeInsets.bottom = -(image.size.height + spacing)
}
self.titleEdgeInsets = titleEdgeInsets
// raise the image and push it right so it appears centered
// above the text
var imageEdgeInsets = UIEdgeInsets.zero
if let text = self.titleLabel?.text, let font = self.titleLabel?.font {
let attributes = [NSFontAttributeName: font]
let titleSize = text.size(attributes: attributes)
imageEdgeInsets.top = -(titleSize.height + spacing)
imageEdgeInsets.right = -titleSize.width
}
self.imageEdgeInsets = imageEdgeInsets
super.layoutSubviews()
}
Ответ 5
Здесь есть несколько отличных примеров, но я не мог заставить это работать во всех случаях, когда также имеет дело с несколькими строками текста (перенос текста). Чтобы, наконец, получить его на работу, я объединил пару методов:
-
Я использовал пример Джесси Кроссена выше. Однако я установил высоту текста
и я добавил возможность указать горизонтальное текстовое поле.
Поля полезны, если разрешить перенос текста, чтобы он не попадал
край кнопки:
// the space between the image and text
CGFloat spacing = 10.0;
float textMargin = 6;
// get the size of the elements here for readability
CGSize imageSize = picImage.size;
CGSize titleSize = button.titleLabel.frame.size;
CGFloat totalHeight = (imageSize.height + titleSize.height + spacing); // get the height they will take up as a unit
// lower the text and push it left to center it
button.titleEdgeInsets = UIEdgeInsetsMake( 0.0, -imageSize.width +textMargin, - (totalHeight - titleSize.height), +textMargin ); // top, left, bottom, right
// the text width might have changed (in case it was shortened before due to
// lack of space and isn't anymore now), so we get the frame size again
titleSize = button.titleLabel.bounds.size;
button.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + spacing), 0.0, 0.0, -titleSize.width ); // top, left, bottom, right
-
Убедитесь, что вы устанавливаете текстовую метку для обертывания
button.titleLabel.numberOfLines = 2;
button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
button.titleLabel.textAlignment = UITextAlignmentCenter;
-
В основном это будет работать. Однако у меня были несколько кнопок, которые не отображали бы их изображение правильно. Изображение было либо сдвинуто вправо, либо влево (оно не было центрировано). Поэтому я использовал метод переопределения макета UIButton, чтобы заставить центр изображения быть центрированным.
@interface CategoryButton : UIButton
@end
@implementation CategoryButton
- (void)layoutSubviews
{
// Allow default layout, then center imageView
[super layoutSubviews];
UIImageView *imageView = [self imageView];
CGRect imageFrame = imageView.frame;
imageFrame.origin.x = (int)((self.frame.size.width - imageFrame.size.width)/ 2);
imageView.frame = imageFrame;
}
@end
Ответ 6
Я сделал метод ответа @TodCunningham
-(void) AlignTextAndImageOfButton:(UIButton *)button
{
CGFloat spacing = 2; // the amount of spacing to appear between image and title
button.imageView.backgroundColor=[UIColor clearColor];
button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
button.titleLabel.textAlignment = UITextAlignmentCenter;
// get the size of the elements here for readability
CGSize imageSize = button.imageView.frame.size;
CGSize titleSize = button.titleLabel.frame.size;
// lower the text and push it left to center it
button.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
// the text width might have changed (in case it was shortened before due to
// lack of space and isn't anymore now), so we get the frame size again
titleSize = button.titleLabel.frame.size;
// raise the image and push it right to center it
button.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
}
Ответ 7
Не сражайтесь с системой. Если ваши макеты становятся слишком сложными для управления с помощью Interface Builder +, возможно, с некоторым простым кодом конфигурации, сделайте макеты вручную проще с помощью layoutSubviews
- для чего это! Все остальное будет означать хаки.
Создайте подкласс UIButton и переопределите его метод layoutSubviews
, чтобы программно выровнять текст и изображение. Или используйте что-то вроде https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h, чтобы вы могли реализовать layoutSubviews с помощью блока.
Ответ 8
Подкласс UIButton
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat spacing = 6.0;
CGSize imageSize = self.imageView.image.size;
CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake(self.frame.size.width, self.frame.size.height - (imageSize.height + spacing))];
self.imageView.frame = CGRectMake((self.frame.size.width - imageSize.width)/2, (self.frame.size.height - (imageSize.height+spacing+titleSize.height))/2, imageSize.width, imageSize.height);
self.titleLabel.frame = CGRectMake((self.frame.size.width - titleSize.width)/2, CGRectGetMaxY(self.imageView.frame)+spacing, titleSize.width, titleSize.height);
}
Ответ 9
Обновленный ответ Джесси Кроссен для Swift 4:
extension UIButton {
func alignVertical(spacing: CGFloat = 6.0) {
guard let imageSize = self.imageView?.image?.size,
let text = self.titleLabel?.text,
let font = self.titleLabel?.font
else { return }
self.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)
let labelString = NSString(string: text)
let titleSize = labelString.size(withAttributes: [kCTFontAttributeName as NSAttributedStringKey: font])
self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0.0, bottom: 0.0, right: -titleSize.width)
let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
self.contentEdgeInsets = UIEdgeInsets(top: edgeOffset, left: 0.0, bottom: edgeOffset, right: 0.0)
}
}
Используйте этот способ:
override func viewDidLayoutSubviews() {
button.alignVertical()
}
Ответ 10
Ничего плохого в других ответах, однако я просто хотел бы отметить, что такое же поведение можно визуально визуализировать в Xcode, используя нулевые строки кода. Это решение полезно, если вам не нужно вычисленное значение или вы создаете раскадровку /xib (иначе применяются другие решения).
Примечание. Я понимаю, что вопрос OP - это код, требующий кода. Я просто предоставляю этот ответ для полноты и в качестве логической альтернативы для тех, кто использует раскадровки /xibs.
Чтобы изменить интервал между изображениями, заголовками и видами содержимого кнопки с помощью кросс-вложений, вы можете выбрать кнопку/элемент управления и открыть инспектор атрибутов. Прокрутите вниз до середины инспектора и найдите раздел для вложений Edge.
![edge-insets]()
Кроме того, вы можете получить доступ и изменить специальные вставки кромки для заголовка, изображения или содержимого.
![menu-options]()
Ответ 11
С помощью этого фрагмента кода вы получите что-то вроде этого ![title and image alignment]()
extension UIButton {
func alignTextUnderImage() {
guard let imageView = imageView else {
return
}
self.contentVerticalAlignment = .Top
self.contentHorizontalAlignment = .Center
let imageLeftOffset = (CGRectGetWidth(self.bounds) - CGRectGetWidth(imageView.bounds)) / 2//put image in center
let titleTopOffset = CGRectGetHeight(imageView.bounds) + 5
self.imageEdgeInsets = UIEdgeInsetsMake(0, imageLeftOffset, 0, 0)
self.titleEdgeInsets = UIEdgeInsetsMake(titleTopOffset, -CGRectGetWidth(imageView.bounds), 0, 0)
}
}
Ответ 12
Расширение UIButton с синтаксисом Swift 3+:
extension UIButton {
func alignImageAndTitleVertically(padding: CGFloat = 6.0) {
let imageSize: CGSize = imageView!.image!.size
titleEdgeInsets = UIEdgeInsetsMake(0.0, -imageSize.width, -(imageSize.height + padding), 0.0)
let labelString = NSString(string: titleLabel!.text!)
let titleSize = labelString.size(attributes: [NSFontAttributeName: titleLabel!.font])
self.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + padding), 0.0, 0.0, -titleSize.width)
let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
self.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0)
}
}
Оригинальный ответ: fooobar.com/questions/33932/...
Ответ 13
Использование button.titleLabel.frame.size.width
отлично работает только до тех пор, пока метка недостаточно коротка, чтобы не быть усеченной. Когда текст ярлыка получает усеченное позиционирование, он не работает. Принимая
CGSize titleSize = [[[button titleLabel] text] sizeWithFont:[[button titleLabel] font]];
работает для меня, даже если текст ярлыка усечен.
Ответ 14
Просто небольшое изменение в ответе Джесси Кроссен сделало его идеальным для меня:
вместо:
CGSize titleSize = button.titleLabel.frame.size;
Я использовал это:
CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName:button.titleLabel.font}];
Ответ 15
Я посмотрел на существующие ответы, но я также обнаружил, что установка рамки кнопки является важным первым шагом.
Вот функция, которую я использую, которая позаботится об этом:
const CGFloat kImageTopOffset = -15;
const CGFloat kTextBottomOffset = -25;
+ (void) centerButtonImageTopAndTextBottom: (UIButton*) button
frame: (CGRect) buttonFrame
text: (NSString*) textString
textColor: (UIColor*) textColor
font: (UIFont*) textFont
image: (UIImage*) image
forState: (UIControlState) buttonState
{
button.frame = buttonFrame;
[button setTitleColor: (UIColor*) textColor
forState: (UIControlState) buttonState];
[button setTitle: (NSString*) textString
forState: (UIControlState) buttonState ];
[button.titleLabel setFont: (UIFont*) textFont ];
[button setTitleEdgeInsets: UIEdgeInsetsMake( 0.0, -image.size.width, kTextBottomOffset, 0.0)];
[button setImage: (UIImage*) image
forState: (UIControlState) buttonState ];
[button setImageEdgeInsets: UIEdgeInsetsMake( kImageTopOffset, 0.0, 0.0,- button.titleLabel.bounds.size.width)];
}
Ответ 16
Или вы можете просто использовать эту категорию:
@interface UIButton (VerticalLayout)
- (void)centerVerticallyWithPadding:(float)padding;
- (void)centerVertically;
@end
@implementation UIButton (VerticalLayout)
- (void)centerVerticallyWithPadding:(float)padding
{
CGSize imageSize = self.imageView.frame.size;
CGSize titleSize = self.titleLabel.frame.size;
CGFloat totalHeight = (imageSize.height + titleSize.height + padding);
self.imageEdgeInsets = UIEdgeInsetsMake(- (totalHeight - imageSize.height),
0.0f,
0.0f,
- titleSize.width);
self.titleEdgeInsets = UIEdgeInsetsMake(0.0f,
- imageSize.width,
- (totalHeight - titleSize.height),
0.0f);
}
- (void)centerVertically
{
const CGFloat kDefaultPadding = 6.0f;
[self centerVerticallyWithPadding:kDefaultPadding];
}
@end
Ответ 17
Мой прецедент делает неуправляемые вставки:
- фоновое изображение на кнопке остается последовательным
- динамический текст и изменения изображения, где длина строки и размер изображения изменяются.
Это то, что я закончил, и я очень доволен этим:
-
Создайте кнопку на раскадровке с фоновым изображением (круглый круг с размытием и цветом).
-
Объявить UIImageView в моем классе:
@implementation BlahViewController {
UIImageView *_imageView;
}
-
Создайте экземпляр изображения в init:
-(id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
_imageView = [[UIImageView alloc] initWithCoder:aDecoder];
}
return self;
}
-
В viewDidLoad добавьте новый слой к кнопке для нашего изображения и установите выравнивание текста:
[self.btn addSubview:_imageView];
[self.btn.titleLabel setTextAlignment:NSTextAlignmentCenter];
-
В методе нажатия кнопки добавьте свое выбранное оверлейное изображение в изображение, размер его, чтобы он соответствовал изображению, и центрируйте его в кнопке, но переместите его вверх 15, чтобы я мог поместить текст ниже:
[_imageView setImage:[UIImage imageNamed:@"blahImageBlah]];
[_imageView sizeToFit];
_imageView.center = CGPointMake(ceilf(self.btn.bounds.size.width / 2.0f),
ceilf((self.btn.bounds.size.height / 2.0f) - 15));
[self.btn setTitle:@"Some new text" forState:UIControlStateNormal];
Примечание: ceilf() важно обеспечить его на границе пикселя для качества изображения.
Ответ 18
Предполагая, что вы хотите, чтобы текст и изображение были центрированы по горизонтали, изображение над текстом:
Центрируйте текст из конструктора интерфейса и добавьте верхнюю вставку (место для изображения). (оставьте левую вставку равной 0). Используйте конструктор интерфейса, чтобы выбрать изображение - фактическая позиция будет установлена из кода, поэтому не беспокойтесь, что в IB это не будет выглядеть нормально. В отличие от других ответов выше, это действительно работает во всех поддерживаемых версиях ios (5,6 и 7).
В коде просто отбросьте ImageView кнопки (установив изображение кнопки в нуль) после захвата изображения (это также автоматически центрирует текст, завернутый, если необходимо). Затем создайте свой собственный ImageView с тем же размером кадра и изображением и расположите его посередине.
Таким образом вы все равно можете выбрать изображение из построителя интерфейса (хотя он не будет выровнен в IB, как в симуляторе, но опять же, другие решения не совместимы во всех поддерживаемых версиях ios)
Ответ 19
Я пытался сделать это, потому что не смог получить размер изображения и ширину текста на моем конструкторе представлений. Два незначительных изменения на Джесси ответ помогли мне:
CGFloat spacing = 3;
self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - image.size.width, - (image.size.height + spacing), 0.0);
CGSize titleSize = [name sizeWithAttributes:@{NSFontAttributeName:self.titleLabel.font}];
self.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
Изменение:
- Использование
[NSString sizeWithAttributes]
для получения ширины текста;
- Получить размер изображения непосредственно на
UIImage
вместо UIImageView
Ответ 20
Это хорошо работает для меня, для нескольких кнопок, с различной шириной изображения и различной длиной заголовка:
Подкласс UIButton
override func layoutSubviews() {
super.layoutSubviews()
if let image = imageView?.image {
let margin = 30 - image.size.width / 2
let titleRect = titleRectForContentRect(bounds)
let titleOffset = (bounds.width - titleRect.width - image.size.width - margin) / 2
contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
imageEdgeInsets = UIEdgeInsetsMake(0, margin, 0, 0)
titleEdgeInsets = UIEdgeInsetsMake(0, (bounds.width - titleRect.width - image.size.width - margin) / 2, 0, 0)
}
}
Ответ 21
Работает отлично для кнопки размером 80x80 пикселей.
[self.leftButton setImageEdgeInsets:UIEdgeInsetsMake(0, 10.0, 20.0, 10.0)];
[self.leftButton setTitleEdgeInsets:UIEdgeInsetsMake(60, -75.0, 0.0, 0.0)];
Ответ 22
Я сделал некоторую настройку, чтобы сделать изображение выровненным в центре горизонтали:
// the space between the image and text
let spacing = CGFloat(36.0);
// lower the text and push it left so it appears centered
// below the image
let imageSize = tutorialButton.imageView!.frame.size;
tutorialButton.titleEdgeInsets = UIEdgeInsetsMake(
0, -CGFloat(imageSize.width), -CGFloat(imageSize.height + spacing), 0.0);
// raise the image and push it right so it appears centered
// above the text
let titleSize = tutorialButton.titleLabel!.frame.size;
tutorialButton.imageEdgeInsets = UIEdgeInsetsMake(
-CGFloat(titleSize.height + spacing), CGFloat((tutorialButton.frame.width - imageSize.width) / 2), 0.0, -CGFloat(titleSize.width));
Ответ 23
Обязательно ли использовать кросс-вставки? Если нет, вы можете попытаться позиционировать отношение к родительскому представлению центра
extension UIButton
{
func centerImageAndTextVerticaAlignment(spacing: CGFloat)
{
var titlePoint : CGPoint = convertPoint(center, fromView:superview)
var imageViewPoint : CGPoint = convertPoint(center, fromView:superview)
titlePoint.y += ((titleLabel?.size.height)! + spacing)/2
imageViewPoint.y -= ((imageView?.size.height)! + spacing)/2
titleLabel?.center = titlePoint
imageView?.center = imageViewPoint
}
}
Ответ 24
Вам нужно переместить изображение вправо по ширине текста. Затем переместите текст влево по ширине изображения.
UIEdgeInsets imageEdgeInsets = self.remoteCommandsButtonLights.imageEdgeInsets;
imageEdgeInsets.left = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:[button.titleLabel font]}].width;
imageEdgeInsets.bottom = 14.0;
button.imageEdgeInsets = imageEdgeInsets;
UIEdgeInsets titleEdgeInsets = self.remoteCommandsButtonLights.titleEdgeInsets;
titleEdgeInsets.left = -button.currentImage.size.width;
titleEdgeInsets.top = 20.0;
button.titleEdgeInsets = titleEdgeInsets;
Затем отрегулируйте верхнюю и нижнюю вставки, чтобы отрегулировать ось Y. Вероятно, это может быть сделано программно, но должно быть постоянным для вашего размера изображения. В то время как наборы X-оси должны будут меняться в зависимости от размера текстовой метки в каждой кнопке.
Ответ 25
Добавьте этот код в расширение Swift 4.2
func moveImageLeftTextCenter(imagePadding: CGFloat = 30.0){
guard let imageViewWidth = self.imageView?.frame.width else{return}
guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
self.contentHorizontalAlignment = .left
imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imagePadding - imageViewWidth / 2, bottom: 0.0, right: 0.0)
titleEdgeInsets = UIEdgeInsets(top: 0.0, left: (bounds.width - titleLabelWidth) / 2 - imageViewWidth, bottom: 0.0, right: 0.0)
}
func moveImageRIghtTextCenter(imagePadding: CGFloat = 30.0){
guard let imageViewWidth = self.imageView?.frame.width else{return}
guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
self.contentHorizontalAlignment = .right
imageEdgeInsets = UIEdgeInsets(top: 0.0, left:0.0 , bottom: 0.0, right: imagePadding - imageViewWidth / 2)
titleEdgeInsets = UIEdgeInsets(top: 0.0, left:0.0 , bottom: 0.0, right:(bounds.width - titleLabelWidth) / 2 - imageViewWidth)
}
Ответ 26
Просто скинуть мои 2 цента, это сработало для меня:
extension UIButton {
public func centerImageAndTextVertically(spacing: CGFloat) {
layoutIfNeeded()
let contentFrame = contentRect(forBounds: bounds)
let imageFrame = imageRect(forContentRect: contentFrame)
let imageLeftInset = bounds.size.width * 0.5 - imageFrame.size.width * 0.5
let imageTopInset = -(imageFrame.size.height + spacing * 0.5)
let titleFrame = titleRect(forContentRect: contentFrame)
let titleLeftInset = ((bounds.size.width - titleFrame.size.width) * 0.5) - imageFrame.size.width
let titleTopInmset = titleFrame.size.height + spacing * 0.5
imageEdgeInsets = UIEdgeInsets(top: imageTopInset, left: imageLeftInset, bottom: 0, right: 0)
titleEdgeInsets = UIEdgeInsets(top: titleTopInmset, left: titleLeftInset, bottom: 0, right: 0)
}
}