Как поместить изображение на правой стороне текста в кнопке UIB?

300

Я не хочу использовать подпредставление, если я могу избежать этого. Я хочу UIButtonс фоновым изображением, текстом и изображением в нем. Прямо сейчас, когда я это делаю, изображение находится на левой стороне текста. Фоновое изображение, текст и изображение имеют разные состояния подсветки.

jasongregori
источник
Чтобы добавить еще один «хак» к растущему списку: вы можете установить attribuTTitle кнопки для приписанной строки, содержащей заголовок вашей кнопки + пробел + изображение (как NSTextAttachment). Возможно, вам придется изменить границы вложения, чтобы выровнять его так, как вы хотите (см. Stackoverflow.com/questions/26105803/… ).
Манав

Ответы:

266

Несмотря на то, что некоторые из предложенных ответов очень креативны и чрезвычайно умны, самое простое решение заключается в следующем:

button.semanticContentAttribute = UIApplication.shared
    .userInterfaceLayoutDirection == .rightToLeft ? .forceLeftToRight : .forceRightToLeft

Так просто, как, что. В качестве бонуса, изображение будет слева на правой стороне слева.

РЕДАКТИРОВАТЬ : как вопрос был задан несколько раз, это iOS 9 + .

Вениамин
источник
89
Я не могу поверить, что этот ответ был принят. Никто не делает локализаций для своих приложений?
Золтан
6
@pallzoltan: это отвечает на вопрос (т. е. «Как поместить изображение с правой стороны текста в кнопке UIButton?»). При чем тут локализация?
Бенджамин
17
Существует не так много ситуаций, когда вы не хотите, чтобы ваш макет был «перевернут» на языках RTL. Непосредственная настройка semanticContentAttribute- это просто взлом / обходной путь, а не реальное решение.
Золтан
6
Мой подход заключается в том, что вы не знаете, что строит человек, задающий вопрос, поэтому всегда лучше учитывать гибкость макета.
Золтан
2
@ Zoltán локализация не проблема, просто инвертируйте свойство в зависимости от текущей локали.
мужчина
561

Самое простое решение:

iOS 10 и выше, Swift:

button.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
button.titleLabel?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
button.imageView?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)

До iOS 10, Swift / Obj-C:

button.transform = CGAffineTransformMakeScale(-1.0, 1.0);
button.titleLabel.transform = CGAffineTransformMakeScale(-1.0, 1.0);
button.imageView.transform = CGAffineTransformMakeScale(-1.0, 1.0);
Ляу Цзянь Цзе
источник
8
Я использовал это для представления заголовка панели навигации, и был сбой. Это нормально, когда он впервые загружен, но когда вы нажимаете контроллер представления и извлекаете его, заголовок переворачивается.
funct7
@WoominJoshPark Интересно ... Я могу только догадываться, что это потому, что преобразование внутренне анимировано для навигационной поп-анимации.
Ляу Цзянь Цзе
1
Я обнаружил, что если это вызывает жалобы на конфликты ограничений автоматического размещения во время выполнения, это можно исправить, добавив это в layoutSubviews ()
Vlad
1
Как я могу поместить больше места между текстом и изображением?
rohinb
2
@rohinb @ jose920405 Попробуйте установить ImageEdgeInsets и ContentEdgeInsets для заполнения (помните, что они были перевернуты). Например button.ImageEdgeInsets = new UIEdgeInsets(0, -leftPadding, 0, leftPadding); button.ContentEdgeInsets = new UIEdgeInsets(0, 0, 0, leftPadding);. Это в Xamarin, но достаточно легко перевести на Swift / Obj-C.
Ли Ричардсон
269

ОБНОВЛЕНО ДЛЯ XCODE 9 (через Интерфейсный Разработчик)

Есть более простой способ от Interface Builder .

Выберите UIButton и выберите эту опцию в View Utilities> Semantic :

слева направо введите описание изображения здесь Это оно! Красиво и просто!

ДОПОЛНИТЕЛЬНО - 2-й шаг:

Если вы хотите настроить расстояние между изображением и заголовком, вы можете изменить здесь вставку изображения :

введите описание изображения здесь

Надеюсь, это поможет!

Виктор Риус
источник
2
В Xcode 9.0 beta 5 (9M202q) вы, к сожалению, видите результат только во время выполнения - в раскадровке он все еще показывает изображение слева. Также обратите внимание, что из-за этого требуется несколько проб и ошибок, чтобы установить правильные вставки.
PDK
3
Пожалуйста, не делайте так - это нарушает локализацию для языков справа налево.
jsadler
169

Подкласс UIButton совершенно не нужен. Вместо этого вы можете просто установить высокое левое значение для вставки изображения и маленькое правое значение для заголовка. Что-то вроде этого:

button.imageEdgeInsets = UIEdgeInsetsMake(0., button.frame.size.width - (image.size.width + 15.), 0., 0.);
button.titleEdgeInsets = UIEdgeInsetsMake(0., 0., 0., image.size.width);
Бен Барон
источник
3
Это сработало, но просто помните, что сегодня с autolayout вы должны делать это на viewDidAppear, а не на viewDidLoad
Hola Soy Edu Feliz Navidad
91

Я отдаю Inspire48 честь этому. Основываясь на его предложении и глядя на этот другой вопрос, я придумал это. Подкласс UIButton и переопределить эти методы.

@implementation UIButtonSubclass

- (CGRect)imageRectForContentRect:(CGRect)contentRect
{
    CGRect frame = [super imageRectForContentRect:contentRect];
    frame.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(frame) -  self.imageEdgeInsets.right + self.imageEdgeInsets.left;
    return frame;
}

- (CGRect)titleRectForContentRect:(CGRect)contentRect
{
    CGRect frame = [super titleRectForContentRect:contentRect];
    frame.origin.x = CGRectGetMinX(frame) - CGRectGetWidth([self imageRectForContentRect:contentRect]);
    return frame;
}

@end
jasongregori
источник
3
UIButton является кластером классов и не должен быть разделен на подклассы.
Скотт Берревоэтс
50
Это не так, в документации явно упоминаются подклассы и предоставляются методы, которые вы должны переопределить для пользовательского поведения макета.
Тарк
2
developer.apple.com/library/ios/documentation/uikit/reference/... buttonWithType If you subclass UIButton, this method does not return an instance of your subclass. If you want to create an instance of a specific subclass, you must alloc/init the button directly и backgroundRectForBoundsподклассы , которые обеспечивают пользовательские фоновые украшения могут переопределить этот метод и возвращать измененные границы не прямоугольник , чтобы предотвратить кнопку от рисования на любом пользовательском content.` Ни упоминают те конкретные методы, но я предполагаю, что они не возражают против подклассов.
Кристоферкоттон
1
Похоже, эта формула лучше подходит для зеркального отображения рамки изображения: frame.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(frame) - self.imageEdgeInsets.right + self.imageEdgeInsets.left - frame.origin.x;она работает лучше и для UIControlContentHorizontalAlignmentCenterдругих ...
k06a
@ GwendalRoué То, что он короче, не значит, что он лучше. Это более хакерский способ, и он заставляет кнопку игнорировать фактические вставки и может сломаться на языках справа налево. С этим ответом у вас есть полный контроль над макетом
Accatyyc
76

Просто обновите вставки, когда название будет изменено. Вы должны компенсировать вставку с помощью равной и противоположной вставки с другой стороны.

[thebutton setTitle:title forState:UIControlStateNormal];
thebutton.titleEdgeInsets = UIEdgeInsetsMake(0, -thebutton.imageView.frame.size.width, 0, thebutton.imageView.frame.size.width);
thebutton.imageEdgeInsets = UIEdgeInsetsMake(0, thebutton.titleLabel.frame.size.width, 0, -thebutton.titleLabel.frame.size.width);
Петр Томасик
источник
3
Возможно, вы захотите добавить [thebutton.titleLabel sizeToFit];раньше. Ширина может быть нулевой, если вы не запустили макет. То же самое касается размера изображения (просто используйте UIImage.size вместо размера imageView)
delrox
@delrox хорошая мысль. Можно использовать titleWidth = [self.titleLabel sizeThatFits:CGSizeMake(CGFLOAT_MAX, self.bounds.size.height)].width;(или если вы обеспокоены тем, что рамка кнопки еще не установлена, используйте CGFLOAT_MAX для высоты) иimageWidth = self.currentImage.size.width;
Дейв Голдман
1
Прекрасно работает на viewDidLayoutSubviews
Гвендал Руэ
Я должен был поместить это в layoutSubviewsмоем UITableViewCellподклассе, но это работает хорошо. Спасибо!
RyanG
60

Все эти ответы по состоянию на январь 2016 года не нужны. В Интерфейсном Разработчике установите View Semantic на Force Right-to-Left, или, если вы предпочитаете программный способ, semanticContentAttribute = .forceRightToLeftЭто приведет к тому, что изображение появится справа от вашего текста.

barndog
источник
5
К сожалению, он не поддерживает IOS старше 9. Тем не менее хороший ответ, хотя.
Эдди
1
Мне грустно сообщать, что установка этого на UIButton, который затем используется для UIBarButtonItem, не привела к каким-либо изменениям.
Амелия
Как упомянул @Amelia, он не сработает, если вы позвоните UIBarButtonItem(customView: button), но сработает, если вы поместите кнопку в какое-то пустое представление
tt.Kilew
@ tt.Kilew, используя XCode 8.1, вы работаете. Я устанавливаю uiButton.semanticContentAttribute = .forceRightToLeft и предоставляю let nextButton = UIBarButtonItem (customView: uiButton)
Евгений Бирюков,
53

В конструкторе интерфейса вы можете настроить параметры Edge Insets для UIButton, отдельно для каждой из трех частей: контент, изображение, заголовок

введите описание изображения здесь введите описание изображения здесь

Xcode 8:

введите описание изображения здесь

Геннадий Рябкин
источник
3
на самом деле лучший ответ, на мой взгляд, это stackoverflow.com/a/39013315/1470374 ))
Геннадий Рябкин
25

Обновление: Swift 3

class ButtonIconRight: UIButton {
    override func imageRect(forContentRect contentRect:CGRect) -> CGRect {
        var imageFrame = super.imageRect(forContentRect: contentRect)
        imageFrame.origin.x = super.titleRect(forContentRect: contentRect).maxX - imageFrame.width
        return imageFrame
    }

    override func titleRect(forContentRect contentRect:CGRect) -> CGRect {
        var titleFrame = super.titleRect(forContentRect: contentRect)
        if (self.currentImage != nil) {
            titleFrame.origin.x = super.imageRect(forContentRect: contentRect).minX
        }
        return titleFrame
    }
}

Оригинальный ответ для Swift 2:

Решение, которое обрабатывает все горизонтальные выравнивания, с примером реализации Swift. Просто переведите на Objective-C, если это необходимо.

class ButtonIconRight: UIButton {
    override func imageRectForContentRect(contentRect:CGRect) -> CGRect {
        var imageFrame = super.imageRectForContentRect(contentRect)
        imageFrame.origin.x = CGRectGetMaxX(super.titleRectForContentRect(contentRect)) - CGRectGetWidth(imageFrame)
        return imageFrame
    }

    override func titleRectForContentRect(contentRect:CGRect) -> CGRect {
        var titleFrame = super.titleRectForContentRect(contentRect)
        if (self.currentImage != nil) {
            titleFrame.origin.x = CGRectGetMinX(super.imageRectForContentRect(contentRect))
        }
        return titleFrame
    }
}

Также стоит отметить, что он хорошо обрабатывает вставки изображений и заголовков.

Вдохновленный ответом jasongregori;)

Жан-Батист
источник
1
Это решение работало для меня, однако мое изображение нуждалось в некотором пространстве вокруг него, поэтому я добавил следующий код: self.contentEdgeInsets = UIEdgeInsetsMake (10.0, 10.0, 10.0, 10.0)
user1354603
1
Мне нравится этот способ, потому что вы можете добавить @IBDesignableв класс и увидеть, что он перевернулся во время разработки.
Джеймс Туми
Я предпочитаю это решение, потому что оно работает, даже если оно находится на панели навигации.
Эль Ужасный
10

Если это нужно сделать в UIBarButtonItem , следует использовать дополнительное обтекание.
Это будет работать

let view = UIView()
let button = UIButton()
button.setTitle("Skip", for: .normal)
button.setImage(#imageLiteral(resourceName:"forward_button"), for: .normal)
button.semanticContentAttribute = .forceRightToLeft
button.sizeToFit()
view.addSubview(button)
view.frame = button.bounds
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: view)

Это не сработает

let button = UIButton()
button.setTitle("Skip", for: .normal)
button.setImage(#imageLiteral(resourceName:"forward_button"), for: .normal)
button.semanticContentAttribute = .forceRightToLeft
button.sizeToFit()
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
tt.Kilew
источник
7

Вот решение для UIButtonконтента с выравниванием по центру. Этот код выравнивает изображение по правому краю и позволяет использовать его imageEdgeInsetsи titleEdgeInsetsдля драгоценного позиционирования.

введите описание изображения здесь

Подкласс UIButtonс вашим пользовательским классом и добавить:

- (CGRect)imageRectForContentRect:(CGRect)contentRect {
    CGRect frame = [super imageRectForContentRect:contentRect];
    CGFloat imageWidth = frame.size.width;
    CGRect titleRect = CGRectZero;
    titleRect.size = [[self titleForState:self.state] sizeWithAttributes:@{NSFontAttributeName: self.titleLabel.font}];
    titleRect.origin.x = (self.frame.size.width - (titleRect.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    frame.origin.x = titleRect.origin.x + titleRect.size.width - self.imageEdgeInsets.right + self.imageEdgeInsets.left;
    return frame;
}

- (CGRect)titleRectForContentRect:(CGRect)contentRect {
    CGFloat imageWidth = [self imageForState:self.state].size.width;
    CGRect frame = [super titleRectForContentRect:contentRect];
    frame.origin.x = (self.frame.size.width - (frame.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    return frame;
}
Виталий Гоженко
источник
1
Также вы можете добавить IBDESIGNABLE в заголовок класса, чтобы посмотреть его в storyborad yadi.sk/i/fd6Si-BJqzCFD
Николай Шубенков
6

Поскольку решение для преобразования не работает в iOS 11, я решил написать новый подход.

Регулировка кнопок semanticContentAttributeдает нам хорошее изображение справа без необходимости ретрансляции, если текст изменяется. Из-за этого это идеальное решение. Однако мне все еще нужна поддержка RTL. Тот факт, что приложение не может изменить направление компоновки в одном сеансе, легко решает эту проблему.

С учетом сказанного, это довольно просто.

extension UIButton {
    func alignImageRight() {
        if UIApplication.shared.userInterfaceLayoutDirection == .leftToRight {
            semanticContentAttribute = .forceRightToLeft
        }
        else {
            semanticContentAttribute = .forceLeftToRight
        }
    }
}
cnotethegr8
источник
6

Путь расширения

Используя расширение, чтобы установить изображение на правой стороне с пользовательским смещением

   extension UIButton {
    func addRightImage(image: UIImage, offset: CGFloat) {
        self.setImage(image, for: .normal)
        self.imageView?.translatesAutoresizingMaskIntoConstraints = false
        self.imageView?.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0.0).isActive = true
        self.imageView?.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -offset).isActive = true
    }
}
Муса Алматри
источник
4

Swift-Расширить UiButton и поставить эти строки

    if let imageWidth = self.imageView?.frame.width {
        self.titleEdgeInsets = UIEdgeInsetsMake(0, -imageWidth, 0, imageWidth);
    }

    if let titleWidth = self.titleLabel?.frame.width {
        let spacing = titleWidth + 20
        self.imageEdgeInsets = UIEdgeInsetsMake(0, spacing, 0, -spacing);
    }
Pramod
источник
3

Опираясь на элегантное решение Петра Томазика: если вы хотите немного увеличить расстояние между надписью кнопки и изображением , то включите это в свои вставки по краям следующим образом (скопируйте мой код, который отлично работает для меня):

    CGFloat spacing          = 3;
    CGFloat insetAmount      = 0.5 * spacing;

    // First set overall size of the button:
    button.contentEdgeInsets = UIEdgeInsetsMake(0, insetAmount, 0, insetAmount);
    [button sizeToFit];

    // Then adjust title and image insets so image is flipped to the right and there is spacing between title and image:
    button.titleEdgeInsets   = UIEdgeInsetsMake(0, -button.imageView.frame.size.width - insetAmount, 0,  button.imageView.frame.size.width  + insetAmount);
    button.imageEdgeInsets   = UIEdgeInsetsMake(0, button.titleLabel.frame.size.width + insetAmount, 0, -button.titleLabel.frame.size.width - insetAmount);

Спасибо Петр за ваше решение!

Erik

Эрик ван дер Нойт
источник
@lulian: Я недавно использовал решение Ляу Цзянь Цзе (здесь принят ответ), и это прекрасно работает и является очень элегантным решением.
Эрик ван дер Нойт
Это не работает для меня, так как это меняет выравнивание текста.
Юлиан Онофрей
3

Сделай сам. Xcode10, swift4,

Для программного дизайна пользовательского интерфейса

введите описание изображения здесь

 lazy var buttonFilter : ButtonRightImageLeftTitle = {
    var button = ButtonRightImageLeftTitle()
    button.setTitle("Playfir", for: UIControl.State.normal)
    button.setImage(UIImage(named: "filter"), for: UIControl.State.normal)
    button.backgroundColor = UIColor.red
    button.contentHorizontalAlignment = .left
    button.titleLabel?.font = UIFont.systemFont(ofSize: 16)
    return button
}()

Значения вставки края применяются к прямоугольнику, чтобы уменьшить или расширить область, представленную этим прямоугольником. Как правило, вставки краев используются во время компоновки вида для изменения рамки вида. Положительные значения приводят к вставке (или уменьшению) кадра на указанную величину. Отрицательные значения приводят к смещению (или расширению) кадра на указанную величину.

class ButtonRightImageLeftTitle: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        guard imageView != nil else { return }

        imageEdgeInsets = UIEdgeInsets(top: 5, left: (bounds.width - 35), bottom: 5, right: 5)
        titleEdgeInsets = UIEdgeInsets(top: 0, left: -((imageView?.bounds.width)! + 10), bottom: 0, right: 0 )

    }
}

для дизайна пользовательского интерфейса StoryBoard

введите описание изображения здесь введите описание изображения здесь

Назмул Хасан
источник
Есть ли способ сделать это более элегантно?
Запорожченко Александр
2

Взял ответ @ Piotr и превратил его в расширение Swift. Обязательно установите изображение и заголовок, прежде чем вызывать его, чтобы размер кнопок соответствовал требованиям.

extension UIButton {

/// Makes the ``imageView`` appear just to the right of the ``titleLabel``.
func alignImageRight() {
    if let titleLabel = self.titleLabel, imageView = self.imageView {
        // Force the label and image to resize.
        titleLabel.sizeToFit()
        imageView.sizeToFit()
        imageView.contentMode = .ScaleAspectFit

        // Set the insets so that the title appears to the left and the image appears to the right. 
        // Make the image appear slightly off the top/bottom edges of the button.
        self.titleEdgeInsets = UIEdgeInsets(top: 0, left: -1 * imageView.frame.size.width,
            bottom: 0, right: imageView.frame.size.width)
        self.imageEdgeInsets = UIEdgeInsets(top: 4, left: titleLabel.frame.size.width,
            bottom: 4, right: -1 * titleLabel.frame.size.width)
    }
}

}

Ник Яп
источник
2

Быстрый вариант, который делает то, что вы хотите, не играя ни с какими вставками:

class RightImageButton: UIButton {

    override func layoutSubviews() {
        super.layoutSubviews()

        if let  textSize = titleLabel?.intrinsicContentSize(),
                imageSize = imageView?.intrinsicContentSize() {
            let wholeWidth = textSize.width + K.textImageGap + imageSize.width
            titleLabel?.frame = CGRect(
                x: round(bounds.width/2 - wholeWidth/2),
                y: 0,
                width: ceil(textSize.width),
                height: bounds.height)
            imageView?.frame = CGRect(
                x: round(bounds.width/2 + wholeWidth/2 - imageSize.width),
                y: RoundRetina(bounds.height/2 - imageSize.height/2),
                width: imageSize.width,
                height: imageSize.height)
        }
    }

    struct K {
        static let textImageGap: CGFloat = 5
    }

}
Крис
источник
1

Решения, упомянутые здесь, перестали работать, как только я включил Auto Layout . Я должен был придумать свой собственный:

Подкласс UIButton и layoutSubviewsметод переопределения :

//
//  MIThemeButtonImageAtRight.m
//  Created by Lukasz Margielewski on 7/9/13.
//

#import "MIThemeButtonImageAtRight.h"

static CGRect CGRectByApplyingUIEdgeInsets(CGRect frame, UIEdgeInsets insets);

@implementation MIThemeButtonImageAtRight

- (void)layoutSubviews
{
    [super layoutSubviews];

    CGRect contentFrame = CGRectByApplyingUIEdgeInsets(self.bounds, self.contentEdgeInsets);

    CGRect frameIcon = self.imageView.frame;
    CGRect frameText = self.titleLabel.frame;

    frameText.origin.x = CGRectGetMinX(contentFrame) + self.titleEdgeInsets.left;
    frameIcon.origin.x = CGRectGetMaxX(contentFrame) - CGRectGetWidth(frameIcon);

    self.imageView.frame = frameIcon;
    self.titleLabel.frame = frameText;
}

@end

static CGRect CGRectByApplyingUIEdgeInsets(CGRect frame, UIEdgeInsets insets){

    CGRect f = frame;

    f.origin.x += insets.left;
    f.size.width -= (insets.left + insets.right);
    f.origin.y += (insets.top);
    f.size.height -= (insets.top + insets.bottom);

    return f;

}

Результат:

введите описание изображения здесь

Лукаш
источник
1

Swift 3.0 Решение для миграции предоставлено jasongregori

class ButtonIconRight: UIButton {
        override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
            var imageFrame = super.imageRect(forContentRect: contentRect)
           imageFrame.origin.x = super.titleRect(forContentRect: contentRect).maxX - imageFrame.width
        return imageFrame
        }

        override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
            var titleFrame = super.titleRect(forContentRect: contentRect)
            if (self.currentImage != nil) {
                titleFrame.origin.x = super.imageRect(forContentRect: contentRect).minX
            }
            return titleFrame
        }
Сурабх Шарма
источник
1

Я решил не использовать стандартный вид изображения кнопки, потому что предложенные решения для его перемещения казались хакерскими. Это дало мне желаемую эстетику, и было интуитивно понятно изменить положение кнопки, изменив ограничения:

extension UIButton {
    func addRightIcon(image: UIImage) {
        let imageView = UIImageView(image: image)
        imageView.translatesAutoresizingMaskIntoConstraints = false

        addSubview(imageView)

        let length = CGFloat(15)
        titleEdgeInsets.right += length

        NSLayoutConstraint.activate([
            imageView.leadingAnchor.constraint(equalTo: self.titleLabel!.trailingAnchor, constant: 10),
            imageView.centerYAnchor.constraint(equalTo: self.titleLabel!.centerYAnchor, constant: 0),
            imageView.widthAnchor.constraint(equalToConstant: length),
            imageView.heightAnchor.constraint(equalToConstant: length)
        ])
    }
}

кнопка со стрелкой вправо

Марк Хеннингс
источник
Это не отвечает на нажатия, текст тускнеет, но изображение нет
Тедди К
0

Свифт 3:

open override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
    var frame = super.imageRect(forContentRect: contentRect)
    let  imageWidth = frame.size.width
    var titleRect = CGRect.zero
    titleRect.size = self.title(for: self.state)!.size(attributes: [NSFontAttributeName: self.titleLabel!.font])
    titleRect.origin.x = (self.frame.size.width - (titleRect.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    frame.origin.x = titleRect.origin.x + titleRect.size.width - self.imageEdgeInsets.right + self.imageEdgeInsets.left;
    return frame
}

open override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
    var frame = super.titleRect(forContentRect: contentRect)
    if let imageWidth = self.image(for: self.state)?.size.width {
        frame.origin.x = (self.frame.size.width - (frame.size.width + imageWidth)) / 2.0 + self.titleEdgeInsets.left - self.titleEdgeInsets.right;
    }
    return frame
}
Александр Волков
источник
0

Как насчет ограничений? В отличие от semanticContentAttribute, они не меняют семантику. Возможно, что-то вроде этого:

 button.rightAnchorconstraint(equalTo: button.rightAnchor).isActive = true

или в Objective-C:

[button.imageView.rightAnchor constraintEqualToAnchor:button.rightAnchor].isActive = YES;

Предостережения: не проверено, iOS 9+

каменный рабочий дом
источник
0

Чтобы выровнять изображение в UIButton, попробуйте код ниже

btn.contentHorizontalAlignment = .right
Давал Х. Нена
источник
Это не то, о чем автор спрашивал.
Матеуш
0

Попробовав несколько решений по всему интернету, я не достиг точного требования. Таким образом, я закончил писать собственный код утилиты. Публикация, чтобы помочь кому-то в будущем. Проверено на Swift 4.2

// This function should be called in/after viewDidAppear to let view render
    func addArrowImageToButton(button: UIButton, arrowImage:UIImage = #imageLiteral(resourceName: "my_image_name") ) {
        let btnSize:CGFloat = 32
        let imageView = UIImageView(image: arrowImage)
        let btnFrame = button.frame
        imageView.frame = CGRect(x: btnFrame.width-btnSize-8, y: btnFrame.height/2 - btnSize/2, width: btnSize, height: btnSize)
        button.addSubview(imageView)
        //Imageview on Top of View
        button.bringSubviewToFront(imageView)
    }
jeet.chanchawat
источник
0

для этой проблемы вы можете создать UIView внутри «метки с представлением UIImage» и установить класс UIView в качестве UIControl и создать IBAction так, чтобы он был в стороне

введите описание изображения здесь

Сушил Вьяс
источник
0

Свифт 4 и 5

Изменить направление изображения UIButton (RTL и LTR)

extension UIButton {
    func changeDirection(){
       isArabic ? (self.contentHorizontalAlignment = .right) : (self.contentHorizontalAlignment = .left)
        // left-right margin 
        self.imageEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
        self.titleEdgeInsets = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    }
}
Рашид Латиф
источник
Что Utility?
Байрон Кётзее
Я просто удаляю Утилиту, это класс в моем коде, где я могу проверить, является ли выбранный язык арабским или английским
Рашид Латиф
0

Xcode 11.4 Swift 5.2

Для тех, кто пытается отразить стиль кнопки «Назад» с помощью шеврона, вот так:

введите описание изображения здесь

import UIKit

class NextBarButton: UIBarButtonItem {

    convenience init(target: Any, selector: Selector) {

        // Create UIButton
        let button = UIButton(frame: .zero)

        // Set Title
        button.setTitle("Next", for: .normal)
        button.setTitleColor(.systemBlue, for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 17)

        // Configure Symbol
        let config = UIImage.SymbolConfiguration(pointSize: 19.0, weight: .semibold, scale: .large)
        let image = UIImage(systemName: "chevron.right", withConfiguration: config)
        button.setImage(image, for: .normal)

        // Add Target
        button.addTarget(target, action: selector, for: .touchUpInside)

        // Put the Image on the right hand side of the button
        // Credit to liau-jian-jie for this part
        button.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
        button.titleLabel?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
        button.imageView?.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)

        // Customise spacing to match system Back button
        button.imageEdgeInsets = UIEdgeInsets(top: 0.0, left: -18.0, bottom: 0.0, right: 0.0)
        button.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -12.0, bottom: 0.0, right: 0.0)

        self.init(customView: button)
    }
}

Реализация:

override func viewDidLoad() {
    super.viewDidLoad()
    let nextButton = NextBarButton(target: self, selector: #selector(nextTapped))
    navigationItem.rightBarButtonItem = nextButton
}

@objc func nextTapped() {
    // your code
}
rbaldwin
источник
0

Я закончил тем, что создал пользовательскую кнопку, которая позволяет установить изображение из инспектора. Ниже мой код:

import UIKit

@IBDesignable
class CustomButton: UIButton {

    @IBInspectable var leftImage: UIImage? = nil
    @IBInspectable var gapPadding: CGFloat = 0

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        setup()
    }

    func setup() {

        if(leftImage != nil) {
            let imageView = UIImageView(image: leftImage)
            imageView.translatesAutoresizingMaskIntoConstraints = false

            addSubview(imageView)

            let length = CGFloat(16)
            titleEdgeInsets.left += length

            NSLayoutConstraint.activate([
                imageView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: gapPadding),
                imageView.centerYAnchor.constraint(equalTo: self.titleLabel!.centerYAnchor, constant: 0),
                imageView.widthAnchor.constraint(equalToConstant: length),
                imageView.heightAnchor.constraint(equalToConstant: length)
            ])
        }
    }
}

Вы можете настроить значение Gap Padding в Inspector, чтобы настроить расстояние между текстом и изображением.

PS: использовал часть кода из ответа @Mark Hennings

Махендра Лия
источник