Bir UIButton'daki görüntüyü metnin sağ tarafına nasıl koyabilirim?


300

Eğer önleyebilirsem bir alt görünüm kullanmak istemiyorum. UIButtonArka plan resmi, metin ve içinde bir resim olan bir istiyorum . Şimdi, bunu yaptığımda, görüntü metnin sol tarafında. Arka plan resmi, metin ve görüntünün tümü farklı vurgulama durumlarına sahiptir.


Buradaki büyüyen listeye başka bir "kesmek" eklemek için: düğmenin attributedTitle'ını düğme başlığınızı + boşluk + görüntüyü (NSTextAttachment olarak) içeren ilişkilendirilmiş bir dizeye ayarlayabilirsiniz. İstediğiniz şekilde hizalamak için ekin sınırlarını değiştirmeniz gerekebilir (bkz. Stackoverflow.com/questions/26105803/… ).
Manav

Yanıtlar:


266

Önerilen cevapların bazıları çok yaratıcı ve son derece zeki olmasına rağmen, en basit çözüm aşağıdaki gibidir:

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

Kadar basit. Bonus olarak, görüntü sağdan sola yerel ayarların sol tarafında olacaktır.

EDIT : soru birkaç kez sorulduğu gibi, bu iOS 9 + .


89
Bu cevabın kabul edilen cevap olduğuna inanamıyorum. Kimse başvuruları için yerelleştirme yapmıyor mu?
Zoltán

6
@pallzoltan: bu soruya cevap verir (yani. "Görüntüyü bir UIButton'daki metnin sağ tarafına nasıl koyabilirim?"). Yerelleştirmenin bununla ne ilgisi var?
Benjamin

17
Düzeninizin RTL dillerinde "çevrilmesini" istemediğiniz pek çok durum yoktur. Doğrudan ayar semanticContentAttributesadece bir kesmek / geçici çözümdür, gerçek bir çözüm değildir.
Zoltán

6
Benim yaklaşımım, soruyu soran kişinin ne inşa ettiğini bilmemenizdir, bu nedenle düzen için esneklikle her zaman daha iyi sayılır.
Zoltán

2
@ Zoltán yerelleştirmesi bir sorun değildir, sadece geçerli yerel ayara bağlı olarak mülkü ters çevirin.
manmal

561

En basit çözüm:

iOS 10 ve üstü, 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)

İOS 10'dan önce 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
Bunu gezinti çubuğu başlık görünümü için kullandım ve bir aksaklık vardı. İlk yüklendiğinde sorun yok, ancak bir görünüm denetleyicisini itip patlattığınızda başlık ters çevriliyor.
funct7

@WoominJoshPark İlginç ... Bunun sadece dönüşümün navigasyonel pop animasyonları için dahili olarak canlandırılması nedeniyle olduğunu tahmin edebilirim.
Liau Jian Jie

1
Bu, çalışma zamanında autolayout kısıtlama çakışmaları hakkında şikayetlere neden oluyorsa, bunu layoutSubviews ()
Vlad

1
Metin ile görüntü arasına nasıl daha fazla yer açabilirim?
17'de rohinb

2
@rohinb @ jose920405 Dolgu için ImageEdgeInsets ve ContentEdgeInsets'i ayarlamayı deneyin (ters çevrildiklerini unutmayın). Örneğin button.ImageEdgeInsets = new UIEdgeInsets(0, -leftPadding, 0, leftPadding); button.ContentEdgeInsets = new UIEdgeInsets(0, 0, 0, leftPadding);. Bu Xamarin'de, ama Swift / Obj-C'ye kolayca tercüme etmeli.
Lee Richardson

268

XCODE 9 İÇİN GÜNCELLENDİ (Arayüz Oluşturucu ile)

Interface Builder'dan daha kolay bir yol var .

UIButton'u seçin ve Görünüm Yardımcı Programları> Semantik'te bu seçeneği belirleyin :

soldan sağa resim açıklamasını buraya girin Bu kadar! Güzel ve basit!

İSTEĞE BAĞLI - 2. adım:

Görüntü ve başlık arasındaki boşluğu ayarlamak isterseniz, burada Görüntü Eklentisini değiştirebilirsiniz :

resim açıklamasını buraya girin

Umarım yardımcı olur!


2
Xcode 9.0 beta 5'te (9M202q) maalesef yalnızca çalışma zamanında sonucu görürsünüz - film şeridinde hala soldaki görüntüyü gösterir. Ayrıca, bu nedenle doğru eklerin ayarlanması biraz deneme yanılma gerektirdiğini unutmayın.
PDK

3
Lütfen bunu bu şekilde yapmayın - bu, sağdan sola diller için yerelleştirmeyi bozar.
jsadler

169

Alt sınıflama UIButton tamamen gereksizdir. Bunun yerine, görüntü iç metinleri için yüksek bir sol iç metin değeri ve başlık için küçük bir sağ iç metin ayarlayabilirsiniz. Bunun gibi bir şey:

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

3
İşe yaradı, ama sadece autolayout ile bugün viewDidAppear'da değil, viewDidLoad'da yapmanız gerektiğini unutmayınDidLoad
Hola Soy Edu Feliz Navidad

91

Inspire48'e bunun için kredi veriyorum . Onun önerisine dayanarak ve başka bir soruya baktığımda bununla geldim. UIButton öğesini alt sınıflayın ve bu yöntemleri geçersiz kılın.

@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 bir sınıf kümesidir ve alt sınıflara ayrılmamalıdır.
Scott Berrevoets

50
Bu doğru değil, belgeler alt sınıftan açıkça bahsediyor ve özel düzen davranışı için geçersiz kılmanız gereken yöntemler sunuyor.
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 ve backgroundRectForBoundsözel arka plan süsleri sağlayan alt sınıflar, bu yöntemi geçersiz kılabilir ve düğmenin herhangi bir özel içerik üzerinde çizim yapmasını önlemek için değiştirilmiş bir sınır dikdörtgeni döndürebilir. ancak alt sınıfları önemsemediklerini varsayıyorum.
christophercotton

1
Bu formül görüntü çerçevesini yansıtmak için daha iyi görünüyor: ve diğerleri frame.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(frame) - self.imageEdgeInsets.right + self.imageEdgeInsets.left - frame.origin.x;için daha iyi çalışıyor UIControlContentHorizontalAlignmentCenter...
k06a

@ GwendalRoué Daha kısa olması daha iyi olduğu anlamına gelmez. Daha hacimli bir yöntemdir ve düğmenin gerçek ekleri yoksaymasını sağlar ve sağdan sola dillerde kırılabilir. Bu cevapla düzeni tam olarak kontrol edebilirsiniz
Accatyyc

76

Başlık değiştiğinde ekleri güncellemeniz yeterlidir. İç kısmı diğer tarafta eşit ve zıt bir iç metinle telafi etmeniz gerekir.

[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
Daha [thebutton.titleLabel sizeToFit];önce eklemek isteyebilirsiniz . Bir düzeni tetiklemediyseniz genişlik sıfır olabilir. Aynı şey görüntü boyutu için de geçerlidir (imageView boyutu yerine UIImage.size kullanın)
delrox

@ delrox iyi bir nokta. Kullanabilir titleWidth = [self.titleLabel sizeThatFits:CGSizeMake(CGFLOAT_MAX, self.bounds.size.height)].width;(veya henüz oluşturulmamış düğme çerçevesinden endişe ediyorsanız, yükseklik için de CGFLOAT_MAX kullanın) veimageWidth = self.currentImage.size.width;
Dave Goldman


Bu layoutSubviewsbenim UITableViewCellalt sınıf ama onun iyi çalışma yerleştirmek zorunda kaldı . Teşekkürler!
RyanG

60

Bu yanıtların tümü, Ocak 2016 itibarıyla gereksizdir. Arayüz Oluşturucu'da, Semantiği Görüntüle olarak ayarlayın Force Right-to-Leftveya programlı bir şekilde tercih ederseniz, semanticContentAttribute = .forceRightToLeftbu, metninizin sağında görüntünün görünmesine neden olur.


5
Ne yazık ki 9 yaşından büyük ios desteklemiyor. Yine de güzel bir cevap, tho.
Eddie

1
Üzgünüm, daha sonra UIBarButtonItem için kullanılan bir UIButton bu ayarı herhangi bir değişiklik ile sonuçlanmadığını üzücü.
Amelia

@Amelia'nın belirttiği gibi, ararsanız işe yaramaz UIBarButtonItem(customView: button), ancak düğmeyi boş bir görünümün içine
sarırsanız çalışır

@ tt.Kilew, XCode 8.1 kullanarak çalıştırabilirsiniz. UiButton.semanticContentAttribute = .forceRightToLeft'i ayarladım ve nextButton = UIBarButtonItem (customView: uiButton)
Eugene Biryukov


25

Güncelleme: 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 için orijinal cevap:

Swift uygulama örneği ile tüm yatay hizalamaları işleyen bir çözüm. Gerekirse sadece Objective-C'ye çevirin.

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

Ayrıca oldukça iyi görüntü ve başlık iç metinleri ele dikkat çekiyor.

Jasongregori cevap esinlenerek;)


1
Bu çözüm benim için çalıştı, ancak görüntümün etrafında biraz boşluk gerekiyordu, bu yüzden aşağıdaki kodu ekledim: self.contentEdgeInsets = UIEdgeInsetsMake (10.0, 10.0, 10.0, 10.0)
user1354603

1
Bu şekilde hoşuma gidiyor çünkü @IBDesignablesınıfa ekleyebilir ve tasarım zamanında ters çevrilmiş görebilirsiniz.
James Toomey

Bu çözümü tercih ediyorum çünkü gezinti çubuğuna koyulduğunda bile çalışıyor.
El Horrible

10

Bu ihtiyaç yapılacak olursa UIBarButtonItem , görünümde ek sarma kullanılmalıdır
Bu irade işi

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)

Bu işe yaramayacak

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

İşte UIButtonortalanmış hizalanmış içerik için çözüm . Bu kod yapmak görüntü sağ hizalanmış ve kullanımına izin verir imageEdgeInsetsve titleEdgeInsetsdeğerli konumlandırma için.

resim açıklamasını buraya girin

UIButtonÖzel sınıfınızla alt sınıf ekleyin ve ekleyin:

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


6

Dönüşüm çözümünün iOS 11'de çalışmadığı için yeni bir yaklaşım yazmaya karar verdim.

Düğmeleri ayarlamak, semanticContentAttributemetin değişirse, görüntüyü sağa döndürmek zorunda kalmadan bize sağa güzel bir görünüm verir. Bu nedenle ideal çözüm. Ancak yine de RTL desteğine ihtiyacım var. Bir uygulamanın aynı oturumda düzen yönünü değiştirememesi bu sorunu kolayca çözer.

Bununla birlikte, oldukça düz ileri.

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

6

Uzatma Yolu

Özel ofset ile sağ taraftaki görüntüyü ayarlamak için uzantı kullanma

   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'u genişlet ve bu satırları koy

    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

Piotr Tomasik'in zarif çözümü üzerine inşa etmek: düğme etiketi ve görüntü arasında biraz boşluk bırakmak istiyorsanız, bunu aşağıdaki gibi uç eklerinize ekleyin (kodumu buraya benim için mükemmel şekilde kopyalayın):

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

Çözümünüz için teşekkürler Piotr!

Erik


@lulian: Son zamanlarda Liau Jian Jie'nin çözümünü kullanıyorum (burada kabul edilen cevap) ve bu harika bir şekilde çalışıyor ve çok zarif bir çözüm.
Erik van der Neut

Metnin hizalamasını değiştirdiği için bu da benim için işe yaramıyor.
Iulian Onofrei

3

Kendin Yap. Xcode10, swift4,

Programlı UI tasarımı için

resim açıklamasını buraya girin

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

Kenar iç metin değerleri, bu dikdörtgenin temsil ettiği alanı küçültmek veya genişletmek için bir dikdörtgene uygulanır. Genellikle kenar yerleşimleri görünüm düzeni sırasında görünümün çerçevesini değiştirmek için kullanılır. Pozitif değerler çerçevenin belirtilen miktarda eklenmesine (veya küçülmesine) neden olur. Negatif değerler, çerçevenin belirtilen miktarda atılmasına (veya genişletilmesine) neden olur.

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 UI tasarımı için

resim açıklamasını buraya girin resim açıklamasını buraya girin


daha zarif yapmanın bir yolu var mı?
Zaporozhchenko Oleksandr


2

Piotr'un cevabını aldı ve bir Swift uzantısı haline getirdi. Düğmeyi doğru şekilde boyutlandırmak için, aramadan önce resmi ve başlığı ayarladığınızdan emin olun.

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

Herhangi bir iç metinle oynatmadan istediğinizi yapan hızlı bir seçenek:

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

Otomatik Yerleşimi etkinleştirdikten sonra burada belirtilen çözümler çalışmayı durdurdu . Kendime gelmek zorunda kaldım:

Alt sınıf UIButton ve geçersiz kılma layoutSubviewsyöntemi:

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

}

Sonuç:

resim açıklamasını buraya girin


1

jasongregori tarafından verilen swift 3.0 Migration çözümü

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

Standart düğme görüntüsü görünümünü kullanmamaya karar verdim çünkü onu hareket ettirmek için önerilen çözümler kibirli hissetti. Bu bana istenen estetiği getirdi ve kısıtlamaları değiştirerek düğmeyi yeniden konumlandırmak sezgisel:

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

sağ ok düğmesi


Bu, musluklara yanıt vermez, metin kararır, ancak görüntü yanıt vermez
Teddy K

0

Hızlı 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

Kısıtlamalar nasıl olur? SemanticContentAttribute'ın aksine semantiği değiştirmezler. Belki böyle bir şey:

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

veya Objective-C'de:

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

Uyarılar: Test Edilmemiş, iOS 9+


0

UIButton içindeki görüntüyü sağa hizalamak için aşağıdaki kodu deneyin

btn.contentHorizontalAlignment = .right

Yazarın sorduğu şey bu değil.
Mateusz

0

İnternetin dört bir yanından çok sayıda çözüm denedikten sonra tam gereksinimi karşılamıyordum. Böylece özel yardımcı kod yazdım. Gelecekte birisine yardım etmek için yayınlamak. Hızlı 4.2 üzerinde test edildi

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

bu sorun için "UIImage görünümünde etiket" içinde UIView oluşturabilir ve UIView sınıfını bir UIControl olarak ayarlayabilir ve IBAction'ı yanda tuch olarak oluşturabilirsiniz

resim açıklamasını buraya girin


0

Swift 4 ve 5

UIButton görüntüsünün yönünü değiştirme (RTL ve 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)
    }
}

Nedir Utility?
Byron Coetsee

Yardımcı Programı kaldırıyorum, kodumda seçilen dilin Arapça mı yoksa İngilizce mi olduğunu kontrol edebileceğim bir sınıftır
Rashid Latif

0

Xcode 11.4 Swift 5.2

Geri düğmesi stilini chevron ile böyle yansıtmaya çalışan herkes için:

resim açıklamasını buraya girin

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

Uygulama:

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

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

0

Resmin Inspector'dan ayarlanmasına izin veren özel bir düğme oluşturdum. Kodum aşağıdadır:

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

Metin ile görüntü arasındaki boşluğu ayarlamak için Denetçiden Boşluk Dolgusu değerini ayarlayabilirsiniz.

Not: @ Mark Hennings cevabından bazı kod kısmı kullanıldı

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.