Як розмістити зображення в правій частині тексту в UIButton?


300

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


Щоб додати ще один "хак" до зростаючого списку тут: ви можете встановити attributedTitle кнопки на атрибутовану рядок, що містить назву кнопки + пробіл + зображення (як NSTextAttachment). Можливо, вам доведеться виправити межі вкладеного файлу, щоб зрівняти його так, як хочете (див. Stackoverflow.com/questions/26105803/… ).
Manav

Відповіді:


266

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

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

Так просто. Як бонус, зображення буде знаходитись зліва в лівій частині справа.

EDIT : оскільки питання вже задавали кілька разів, це iOS 9 + .


88
Не можу повірити, що ця відповідь була прийнятою. Ніхто не робить локалізації для їх заявок?
Золтан

6
@pallzoltan: це дає відповідь на запитання (тобто "Як я розміщую зображення в правій частині тексту в UIButton?"). Що стосується локалізації?
Бенджамін

16
Не так багато ситуацій, коли ви не хочете, щоб ваш макет був "перевернутий" мовами RTL. Безпосереднє налаштування semanticContentAttribute- це просто хакер / вирішення, а не справжнє рішення.
Золтан

6
Мій підхід полягає в тому, що ви не знаєте, що будує людина, яка задає питання, тому завжди краще розраховувати з гнучкістю для планування.
Золтан

2
@ Локалізація Zoltán не є проблемою, просто переверніть властивість залежно від поточної мови.
manmal

560

Найпростіше рішення:

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
Я знайшов , якщо це викликає скарги autolayout обмежень конфліктів під час виконання може бути виправлено шляхом додавання цього в layoutSubviews ()
Влад

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 досить легко.
Лі Річардсон

268

ОНОВЛЕНО ДЛЯ XCODE 9 (через програму Interface Builder)

Існує простіший спосіб від Інтерфейсу .

Виберіть UIButton і виберіть цей параметр у меню Утиліти перегляду> Семантичний :

зліва направо введіть тут опис зображення Це воно! Приємно і просто!

ОПЦІЙНО - 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
Це спрацювало, але пам’ятайте лише, що сьогодні з автоматичним розкладом ви повинні робити це на 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

3
UIButton - це кластер класів, і його не слід підкласифікувати.
Скотт Берревоєць,

50
Це неправда, в документації явно згадується підкласифікація та надаються методи, які слід перекрити для поведінки власної компонування.
Tark

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підкласи, які надають власні фонові прикраси, можуть замінити цей метод і повернути модифікований прямокутник, щоб кнопка не перетягувала будь-який спеціальний вміст. методи, але я припускаю, що вони не проти підкласів.
Крістоферкотон

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
Gwendal Roué

Мені довелося помістити це layoutSubviewsу своєму UITableViewCellпідкласі, але це добре працює. Дякую!
RyanG

60

Усі ці відповіді станом на січень 2016 року є непотрібними. У програмі Interface Builder встановіть View Semantic на Force Right-to-Leftабо, якщо ви віддаєте перевагу програмний спосіб, semanticContentAttribute = .forceRightToLeftце призведе до того, що зображення з’явиться праворуч від тексту.


5
На жаль, він не підтримує ios старше 9 років. Тим не менш приємна відповідь, тхо.
Едді

1
Мені сумно повідомити, що встановлення цього параметра на UIButton, який потім використовується для UIBarButtonItem, не призвело до жодних змін.
Амелія

Як згадувала @Amelia, вона не працює, якщо ви телефонуєте UIBarButtonItem(customView: button), але працюватиме, якщо
запустити

@ tt.Kilew, використовуючи XCode 8.1, ви працюєте. Я встановлюю uiButton.semanticContentAttribute = .forceRightToLeft і надаю let nextButton = UIBarButtonItem (customView: uiButton)
Євген Бірюков


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)

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
        }
    }
}

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);
    }

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);

Дякую Piotr за ваше рішення!

Ерік


@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

Узяв @ Пьотр відповідь і перетворив його на розширення 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

Згадані тут рішення перестали працювати, як тільки я ввімкнув автоматичний макет . Мені довелося придумати своє:

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

//
//  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

швидкий 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)
        ])
    }
}

кнопка зі стрілкою праворуч


Це не реагує на натискання, текст тьмяніє, але зображення не
Teddy K

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

Спробувавши декілька рішень з Інтернету, я не домагався точної вимоги. Тож я закінчив писати користувацький код утиліти. Публікація, щоб допомогти комусь у майбутньому. Перевірено на швидкій 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)
    }

0

для цього випуску можна створити UIView всередині "label with UIImage view" і встановити клас UIView як UIControl та створити IBAction як tuch up side

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


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
}

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)
            ])
        }
    }
}

Ви можете налаштувати значення зазору пробілу від Інспектора, щоб відрегулювати відстань між текстом і зображенням.

PS: Використовується деяка частина коду з відповіді @Mark Hennings

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.