Wie platziere ich das Bild in einem UIButton auf der rechten Seite des Textes?


300

Ich möchte keine Unteransicht verwenden, wenn ich dies vermeiden kann. Ich möchte ein UIButtonmit einem Hintergrundbild, Text und einem Bild darin. Wenn ich das mache, befindet sich das Bild gerade auf der linken Seite des Textes. Das Hintergrundbild, der Text und das Bild haben unterschiedliche Hervorhebungszustände.


Um der wachsenden Liste hier einen weiteren "Hack" hinzuzufügen: Sie können den Attributtitel der Schaltfläche auf eine Attributzeichenfolge setzen, die Ihren Schaltflächentitel + ein Leerzeichen + das Bild enthält (als NSTextAttachment). Möglicherweise müssen Sie die Grenzen des Anhangs anpassen , damit er wie gewünscht ausgerichtet wird (siehe stackoverflow.com/questions/26105803/… ).
Manav

Antworten:


266

Obwohl einige der vorgeschlagenen Antworten sehr kreativ und äußerst clever sind, lautet die einfachste Lösung wie folgt:

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

So einfach ist das. Als Bonus befindet sich das Bild links von links nach links.

BEARBEITEN : Da die Frage einige Male gestellt wurde, ist dies iOS 9 + .


89
Ich kann nicht glauben, dass diese Antwort akzeptiert wurde. Niemand macht Lokalisierungen für ihre Anwendungen?
Zoltán

6
@pallzoltan: Dies beantwortet die Frage (dh "Wie platziere ich das Bild in einem UIButton auf der rechten Seite des Textes?"). Was hat Lokalisierung damit zu tun?
Benjamin

17
Es gibt nicht viele Situationen, in denen Sie nicht möchten, dass Ihr Layout in RTL-Sprachen "umgedreht" wird. Direkte Einstellung semanticContentAttributeist nur ein Hack / Workaround, keine echte Lösung.
Zoltán

6
Mein Ansatz ist, dass Sie nicht wissen, was die Person, die die Frage stellt, baut, daher ist es immer besser, mit Flexibilität für das Layout zu zählen.
Zoltán

2
@ Zoltán Lokalisierung ist kein Problem, invertieren Sie einfach die Eigenschaft abhängig vom aktuellen Gebietsschema.
Manmal

561

Einfachste Lösung:

iOS 10 und höher, 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)

Vor 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
Ich habe dies für die Titelansicht der Navigationsleiste verwendet und es gab einen Fehler. Es ist in Ordnung, wenn es zum ersten Mal geladen wird, aber wenn Sie einen Ansichts-Controller drücken und ihn öffnen, wird der Titel gespiegelt.
Funktion7

@WoominJoshPark Interessant ... Ich kann nur vermuten, dass dies daran liegt, dass die Transformation intern für Navigations-Pop-Animationen animiert wird.
Liau Jian Jie

1
Ich fand heraus, wenn dies Beschwerden über Autolayout-Einschränkungskonflikte zur Laufzeit verursacht, kann es behoben werden, indem dies in layoutSubviews ()
Vlad

1
Wie kann ich mehr Platz zwischen Text und Bild schaffen?
Rohinb

2
@rohinb @ jose920405 Versuchen Sie, ImageEdgeInsets und ContentEdgeInsets für das Auffüllen festzulegen (beachten Sie, dass sie umgekehrt wurden). Zum Beispiel button.ImageEdgeInsets = new UIEdgeInsets(0, -leftPadding, 0, leftPadding); button.ContentEdgeInsets = new UIEdgeInsets(0, 0, 0, leftPadding);. Das ist in Xamarin, sollte aber leicht genug in Swift / Obj-C übersetzt werden können.
Lee Richardson

268

AKTUALISIERT FÜR XCODE 9 (über Interface Builder)

Es gibt einen einfacheren Weg vom Interface Builder .

Wählen Sie den UIButton und wählen Sie diese Option unter View Utilities> Semantic :

links nach rechts Geben Sie hier die Bildbeschreibung ein Das ist es! Schön und einfach!

OPTIONAL - 2. Schritt:

Wenn Sie den Abstand zwischen dem Bild und dem Titel anpassen möchten, können Sie den Bildeinsatz hier ändern :

Geben Sie hier die Bildbeschreibung ein

Ich hoffe, das hilft!


2
In Xcode 9.0 Beta 5 (9M202q) sehen Sie das Ergebnis leider nur zur Laufzeit - im Storyboard wird das Bild weiterhin links angezeigt. Beachten Sie auch, dass aus diesem Grund einige Versuche erforderlich sind, um die richtigen Einfügungen festzulegen.
PDK

3
Bitte machen Sie es nicht so - dies unterbricht die Lokalisierung für Sprachen von rechts nach links.
Jsadler

169

Das Unterklassen von UIButton ist völlig unnötig. Stattdessen können Sie einfach einen hohen linken Einschubwert für die Bildeinsätze und einen kleinen rechten Einschub für den Titel festlegen. Etwas wie das:

button.imageEdgeInsets = UIEdgeInsetsMake(0., button.frame.size.width - (image.size.width + 15.), 0., 0.);
button.titleEdgeInsets = UIEdgeInsetsMake(0., 0., 0., image.size.width);

3
Es hat funktioniert, aber denken Sie daran, dass Sie es heute mit Autolayout auf viewDidAppear und nicht auf viewDidLoad tun müssen
Hola Soja Edu Feliz Navidad

91

Ich gebe Inspire48 die Ehre dafür. Aufgrund seines Vorschlags und der Betrachtung dieser anderen Frage kam ich auf diese Idee. Unterklasse UIButton und überschreiben diese Methoden.

@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 ist ein Klassencluster und sollte nicht in Unterklassen unterteilt werden.
Scott Berrevoets

50
Dies ist nicht der Fall. In der Dokumentation wird die Unterklasse explizit erwähnt und es werden Methoden bereitgestellt, die Sie für das benutzerdefinierte Layoutverhalten überschreiben sollten.
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 und backgroundRectForBoundsUnterklassen, die benutzerdefinierte Hintergrundverzierungen bereitstellen, können diese Methode überschreiben und ein modifiziertes Begrenzungsrechteck zurückgeben, um zu verhindern, dass die Schaltfläche über benutzerdefinierte Inhalte zeichnet. " Methoden, aber ich nehme an, sie haben nichts gegen Unterklassen.
Christophercotton

1
Sieht so aus, als wäre diese Formel besser für das Spiegeln von Bilderrahmen: frame.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(frame) - self.imageEdgeInsets.right + self.imageEdgeInsets.left - frame.origin.x;Sie funktioniert besser für UIControlContentHorizontalAlignmentCenterund andere ...
k06a

@ GwendalRoué Nur weil es kürzer ist, heißt das nicht, dass es besser ist. Es ist ein hackigerer Weg, und die Schaltfläche ignoriert tatsächliche Einfügungen und kann in Sprachen von rechts nach links unterbrochen werden. Mit dieser Antwort haben Sie die volle Kontrolle über das Layout
Accatyyc

76

Aktualisieren Sie einfach die Einfügungen, wenn der Titel geändert wird. Sie müssen den Einschub durch einen gleichen und entgegengesetzten Einschub auf der anderen Seite kompensieren.

[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
Vielleicht möchten Sie [thebutton.titleLabel sizeToFit];vorher hinzufügen . Die Breite kann Null sein, wenn Sie kein Layout ausgelöst haben. Gleiches gilt für die Bildgröße (verwenden Sie einfach die UIImage.size anstelle der imageView-Größe)
delrox

@delrox guter Punkt. Kann verwenden titleWidth = [self.titleLabel sizeThatFits:CGSizeMake(CGFLOAT_MAX, self.bounds.size.height)].width;(oder wenn Sie besorgt sind, dass der Schaltflächenrahmen noch nicht eingerichtet ist, verwenden Sie CGFLOAT_MAX auch für die Höhe) undimageWidth = self.currentImage.size.width;
Dave Goldman

1
Funktioniert perfekt auf viewDidLayoutSubviews
Gwendal Roué

Ich musste dies in layoutSubviewsmeine UITableViewCellUnterklasse aufnehmen, aber es funktioniert gut. Vielen Dank!
RyanG

60

Alle diese Antworten ab Januar 2016 sind nicht erforderlich. Stellen Sie im Interface Builder die Ansichtssemantik auf ein Force Right-to-Leftoder wenn Sie eine programmatische Methode bevorzugen, semanticContentAttribute = .forceRightToLeftwird das Bild rechts neben Ihrem Text angezeigt.


5
Leider werden ios, die älter als 9 sind, nicht unterstützt. Trotzdem eine nette Antwort.
Eddie

1
Ich bin traurig zu berichten, dass das Festlegen dieser Option auf einem UIButton, der dann für UIBarButtonItem verwendet wird, zu keiner Änderung geführt hat.
Amelia

Wie @Amelia erwähnt, funktioniert es nicht, wenn Sie anrufen UIBarButtonItem(customView: button), aber es funktioniert, wenn Sie die Schaltfläche in eine leere Ansicht
einschließen

@ tt.Kilew, mit XCode 8.1 funktioniert es. Ich setze den uiButton.semanticContentAttribute = .forceRightToLeft und gebe let nextButton = UIBarButtonItem (customView: uiButton)
Eugene Biryukov


25

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

Ursprüngliche Antwort für Swift 2:

Eine Lösung, die alle horizontalen Ausrichtungen mit einem Swift-Implementierungsbeispiel behandelt. Übersetzen Sie bei Bedarf einfach in 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
    }
}

Erwähnenswert ist auch, dass es recht gut mit Bild- und Titeleinfügungen umgehen kann.

Inspiriert von Jasongregori Antwort;)


1
Diese Lösung funktionierte für mich, mein Bild benötigte jedoch etwas Platz, sodass ich den folgenden Code hinzufügte: self.contentEdgeInsets = UIEdgeInsetsMake (10.0, 10.0, 10.0, 10.0)
user1354603

1
Ich mag diesen Weg, weil Sie @IBDesignableder Klasse hinzufügen und sehen können, wie sie zur Entwurfszeit umgedreht wird.
James Toomey

Ich bevorzuge diese Lösung, weil sie sogar in der Navigationsleiste funktioniert.
El Horrible

10

Wenn dies in UIBarButtonItem durchgeführt werden muss , sollte ein zusätzlicher Wrapping in der Ansicht verwendet werden.
Dies funktioniert

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)

Das wird nicht funktionieren

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

Hier ist eine Lösung für UIButtonInhalte mit zentrierter Ausrichtung. Dieser Code macht das Bild rechtsbündig und ermöglicht die Verwendung imageEdgeInsetsund titleEdgeInsetswertvolle Positionierung.

Geben Sie hier die Bildbeschreibung ein

Unterklasse UIButtonmit Ihrer benutzerdefinierten Klasse und fügen Sie hinzu:

- (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
Sie können auch IBDESIGNABLE zum Klassenkopf hinzufügen, um es in der Geschichte yadi.sk/i/fd6Si-BJqzCFD
Nikolay Shubenkov

6

Da die Transformationslösung in iOS 11 nicht funktioniert, habe ich beschlossen, einen neuen Ansatz zu schreiben.

Durch Anpassen der Schaltflächen sehen semanticContentAttributewir das Bild schön rechts, ohne dass wir es weiterleiten müssen, wenn sich der Text ändert. Aus diesem Grund ist es die ideale Lösung. Ich brauche jedoch noch RTL-Unterstützung. Die Tatsache, dass eine App ihre Layoutrichtung in derselben Sitzung nicht ändern kann, behebt dieses Problem auf einfache Weise.

Trotzdem ist es ziemlich einfach.

extension UIButton {
    func alignImageRight() {
        if UIApplication.shared.userInterfaceLayoutDirection == .leftToRight {
            semanticContentAttribute = .forceRightToLeft
        }
        else {
            semanticContentAttribute = .forceLeftToRight
        }
    }
}

6

Verlängerungsweg

Verwenden der Erweiterung, um das Bild auf der rechten Seite mit benutzerdefiniertem Versatz festzulegen

   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 - Erweitern Sie den UiButton und setzen Sie diese Zeilen

    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

Aufbauend auf der eleganten Lösung von Piotr Tomasik: Wenn Sie auch einen gewissen Abstand zwischen der Tastenbeschriftung und dem Bild haben möchten, fügen Sie diesen wie folgt in Ihre Kanteneinfügungen ein (kopieren Sie meinen Code hier, der perfekt für mich funktioniert):

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

Danke Piotr für deine Lösung!

Erik


@lulian: Ich habe stattdessen kürzlich die Lösung von Liau Jian Jie verwendet (die hier akzeptierte Antwort), und das funktioniert hervorragend und ist eine sehr elegante Lösung.
Erik van der Neut

Das funktioniert auch bei mir nicht, da es die Ausrichtung des Textes ändert.
Iulian Onofrei

3

Mach es dir selbst. Xcode10, swift4,

Für programmgesteuertes UI-Design

Geben Sie hier die Bildbeschreibung ein

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

Kanteneinfügungswerte werden auf ein Rechteck angewendet, um den durch dieses Rechteck dargestellten Bereich zu verkleinern oder zu erweitern. In der Regel werden Kanteneinsätze während des Ansichtslayouts verwendet, um den Rahmen der Ansicht zu ändern. Positive Werte bewirken, dass der Rahmen um den angegebenen Betrag eingefügt (oder verkleinert) wird. Negative Werte bewirken, dass der Frame um den angegebenen Betrag versetzt (oder erweitert) wird.

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 )

    }
}

für das StoryBoard-UI-Design

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein


Gibt es eine Möglichkeit, es eleganter zu machen?
Zaporozhchenko Oleksandr


2

Nahm @ Piotrs Antwort und machte es zu einer Swift-Erweiterung. Stellen Sie sicher, dass Sie das Bild und den Titel festlegen, bevor Sie dies aufrufen, damit die Größe der Schaltfläche richtig ist.

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

Eine schnelle Option, die macht, was Sie wollen, ohne mit Insets zu spielen:

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

Die hier genannten Lösungen funktionierten nicht mehr, nachdem ich das automatische Layout aktiviert hatte . Ich musste mir meine eigenen einfallen lassen:

Unterklasse UIButton und Override- layoutSubviewsMethode:

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

}

Ergebnis:

Geben Sie hier die Bildbeschreibung ein


1

schnelle 3.0 Migrationslösung von 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

Ich habe mich entschieden, die Standard-Schaltflächenbildansicht nicht zu verwenden, da sich die vorgeschlagenen Lösungen zum Verschieben hackig anfühlten. Dies brachte mir die gewünschte Ästhetik und es ist intuitiv, den Knopf durch Ändern der Einschränkungen neu zu positionieren:

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

Taste mit Rechtspfeil


Dies reagiert nicht auf Tippen, der Text wird dunkler, das Bild jedoch nicht
Teddy K

0

Swift 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

Wie wäre es mit Einschränkungen? Im Gegensatz zu semanticContentAttribute ändern sie die Semantik nicht. So etwas vielleicht:

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

oder in Ziel-C:

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

Vorsichtsmaßnahmen: Ungetestet, iOS 9+


0

Versuchen Sie den folgenden Code, um das Bild innerhalb von UIButton nach rechts auszurichten

btn.contentHorizontalAlignment = .right

Darum hat der Autor nicht gebeten.
Mateusz

0

Nachdem ich mehrere Lösungen aus dem Internet ausprobiert hatte, erreichte ich nicht die genaue Anforderung. Also habe ich benutzerdefinierten Dienstprogrammcode geschrieben. Posting, um jemandem in Zukunft zu helfen. Getestet auf schnell 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

Für dieses Problem können Sie UIView in "label with UIImage view" erstellen, die UIView-Klasse als UIControl festlegen und IBAction als Tuch-Up-Side erstellen

Geben Sie hier die Bildbeschreibung ein


0

Swift 4 & 5

Ändern Sie die Richtung des UIButton-Bildes (RTL und 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)
    }
}

Was ist Utility?
Byron Coetsee

Ich entferne nur das Dienstprogramm. Es ist eine Klasse in meinem Code, in der ich überprüfen kann, ob die ausgewählte Sprache Arabisch oder Englisch ist
Rashid Latif

0

Xcode 11.4 Swift 5.2

Für alle, die versuchen, den Stil der Zurück-Schaltfläche mit dem Chevron wie folgt zu spiegeln:

Geben Sie hier die Bildbeschreibung ein

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

Implementierung:

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

@objc func nextTapped() {
    // your code
}

0

Am Ende habe ich eine benutzerdefinierte Schaltfläche erstellt, mit der Sie das Bild aus dem Inspektor festlegen können. Unten ist mein Code:

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

Sie können den Wert von Gap Padding im Inspector anpassen, um den Abstand zwischen Text und Bild anzupassen.

PS: Verwendet einen Codeteil aus der Antwort von @Mark Hennings

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.