Bagaimana cara menempatkan gambar di sisi kanan teks dalam UIButton?

300

Saya tidak ingin menggunakan subview jika saya bisa menghindarinya. Saya ingin UIButtondengan gambar latar belakang, teks, dan gambar di dalamnya. Saat ini, ketika saya melakukan itu, gambar ada di sisi kiri teks. Gambar latar belakang, teks, dan gambar semuanya memiliki status sorotan yang berbeda.

jasongregori
sumber
Untuk menambahkan "retasan" lain ke daftar yang sedang tumbuh di sini: Anda dapat mengatur atribut tombol Judul ke string yang dikaitkan berisi judul tombol Anda + spasi + gambar (sebagai NSTextAttachment). Anda mungkin perlu mengubah batas lampiran untuk membuatnya sejajar seperti yang Anda inginkan (lihat stackoverflow.com/questions/26105803/… ).
Manav

Jawaban:

266

Meskipun beberapa jawaban yang disarankan sangat kreatif dan sangat pintar, solusi paling sederhana adalah sebagai berikut:

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

Sesimpel itu. Sebagai bonus, gambar akan berada di sisi kiri di lokal kanan-ke-kiri.

EDIT : karena pertanyaan telah ditanyakan beberapa kali, ini adalah iOS 9+ .

Benjamin
sumber
89
Saya tidak percaya jawaban ini yang diterima. Tidak ada yang melakukan lokalisasi untuk aplikasi mereka?
Zoltán
6
@ palzoltan: ini menjawab pertanyaan (mis. "Bagaimana cara menempatkan gambar di sisi kanan teks dalam UIButton?"). Apa hubungan lokalisasi dengan ini?
Benjamin
17
Tidak ada banyak situasi ketika Anda tidak ingin tata letak Anda "terbalik" dalam bahasa RTL. Pengaturan langsung semanticContentAttributehanyalah hack / solusi, bukan solusi nyata.
Zoltán
6
Pendekatan saya adalah Anda tidak tahu apa yang dibuat oleh orang yang mengajukan pertanyaan, jadi selalu lebih baik hitung dengan fleksibilitas untuk tata letak.
Zoltán
2
@ Lokalisasi Zoltán bukan masalah, cukup balikkan properti tergantung pada lokal saat ini.
manmal
561

Solusi paling sederhana:

iOS 10 & lebih tinggi, 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)

Sebelum 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);
Liau Jian Jie
sumber
8
Saya menggunakan ini untuk tampilan judul bar navigasi dan ada kesalahan. Tidak apa-apa saat pertama kali dimuat, tetapi ketika Anda mendorong pengontrol tampilan dan pop itu, judul akan terbalik.
funct7
@WoominJoshPark Menarik ... Saya hanya bisa menebak bahwa ini adalah karena transformasi tersebut animasi secara internal untuk animasi pop navigasi.
Liau Jian Jie
1
Saya menemukan jika ini menyebabkan keluhan tentang konflik kendala autolayout saat runtime mungkin diperbaiki dengan menambahkan ini di layoutSubviews ()
Vlad
1
Bagaimana saya bisa menempatkan lebih banyak ruang di antara teks dan gambar?
rohinb
2
@rohinb @ jose920405 Cobalah mengatur ImageEdgeInsets dan ContentEdgeInsets untuk padding (dengan mengingat mereka telah terbalik). Sebagai contoh button.ImageEdgeInsets = new UIEdgeInsets(0, -leftPadding, 0, leftPadding); button.ContentEdgeInsets = new UIEdgeInsets(0, 0, 0, leftPadding);. Itu di Xamarin, tetapi harus menerjemahkan ke Swift / Obj-C dengan cukup mudah.
Lee Richardson
269

DIPERBARUI UNTUK XCODE 9 (Via Interface Builder)

Ada cara yang lebih mudah dari Interface Builder .

Pilih UIButton dan pilih opsi ini di View Utilities> Semantic :

kiri ke kanan masukkan deskripsi gambar di sini Itu dia! Bagus dan sederhana!

OPSIONAL - langkah ke-2:

Jika Anda ingin menyesuaikan jarak antara gambar dan judul, Anda dapat mengubah Image Inset di sini:

masukkan deskripsi gambar di sini

Semoga itu bisa membantu!

Victor Rius
sumber
2
Dalam Xcode 9.0 beta 5 (9M202q), Anda sayangnya hanya melihat hasilnya saat runtime — di storyboard masih menampilkan gambar ke kiri. Perhatikan juga bahwa karena ini diperlukan beberapa percobaan dan kesalahan untuk mengatur inset yang benar.
PDK
3
Tolong jangan lakukan ini dengan cara - ini melanggar lokalisasi untuk bahasa kanan-ke-kiri.
jsadler
169

Subclassing UIButton sama sekali tidak perlu. Alih-alih, Anda cukup menetapkan nilai inset kiri tinggi untuk inset gambar, dan inset kanan kecil untuk judul. Sesuatu seperti ini:

button.imageEdgeInsets = UIEdgeInsetsMake(0., button.frame.size.width - (image.size.width + 15.), 0., 0.);
button.titleEdgeInsets = UIEdgeInsetsMake(0., 0., 0., image.size.width);
Ben Baron
sumber
3
Berhasil, tetapi ingatlah bahwa hari ini dengan autolayout Anda harus melakukannya di viewDidAppear dan bukan di viewDidLoad
Hola Soy Edu Feliz Navidad
91

Saya memberi Inspire48 penghargaan untuk yang satu ini. Berdasarkan sarannya dan melihat pertanyaan lain itu saya menemukan ini. Subclass UIButton dan timpa metode ini.

@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
sumber
3
UIButton adalah kluster kelas dan tidak boleh disubklasifikasikan.
Scott Berrevoets
50
Itu tidak benar, dokumentasi secara eksplisit menyebutkan subclassing dan memberikan metode yang Anda harus timpa untuk perilaku tata letak kustom.
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 dan backgroundRectForBoundsSubclasses yang memberikan perhiasan latar belakang kustom dapat menggantikan metode ini dan mengembalikan persegi batas yang dimodifikasi untuk mencegah tombol dari menggambar konten kustom apa pun. `Tidak ada yang menyebutkan spesifik metode, tapi saya berasumsi mereka tidak keberatan subclass.
christophercotton
1
Sepertinya rumus ini lebih baik untuk mirroring bingkai foto: frame.origin.x = CGRectGetMaxX(contentRect) - CGRectGetWidth(frame) - self.imageEdgeInsets.right + self.imageEdgeInsets.left - frame.origin.x;Ini bekerja lebih baik untuk UIControlContentHorizontalAlignmentCenterdan lain-lain ...
k06a
@ GwendalRoué Hanya karena lebih pendek bukan berarti lebih baik. Ini cara peretasan, dan itu membuat tombol mengabaikan insets aktual, dan mungkin pecah dalam bahasa kanan-ke-kiri. Dengan jawaban ini Anda memiliki kontrol penuh terhadap tata letak
Accatyyc
76

Perbarui saja insets ketika judul diubah. Anda perlu mengkompensasi inset dengan inset yang sama dan berlawanan di sisi lain.

[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);
Piotr Tomasik
sumber
3
Anda mungkin ingin menambahkan [thebutton.titleLabel sizeToFit];sebelumnya. Lebar mungkin nol jika Anda belum memicu tata letak. Hal yang sama berlaku untuk ukuran gambar (cukup gunakan ukuran UIImage.size daripada ukuran imageView)
delrox
@delrox poin bagus. Dapat menggunakan titleWidth = [self.titleLabel sizeThatFits:CGSizeMake(CGFLOAT_MAX, self.bounds.size.height)].width;(atau jika Anda khawatir tentang bingkai tombol yang belum dibuat, gunakan CGFLOAT_MAX untuk ketinggian juga) danimageWidth = self.currentImage.size.width;
Dave Goldman
1
Bekerja dengan sempurna pada viewDidLayoutSubviews
Gwendal Roué
Saya harus menempatkan ini di layoutSubviewsdalam UITableViewCellsubkelas saya tetapi ini bekerja dengan baik. Terima kasih!
RyanG
60

Semua jawaban ini, per Januari 2016, tidak perlu. Di Interface Builder, atur Tampilan Semantic ke Force Right-to-Left, atau jika Anda lebih suka cara terprogram, semanticContentAttribute = .forceRightToLeftItu akan menyebabkan gambar muncul di sebelah kanan teks Anda.

barndog
sumber
5
Sayangnya itu tidak mendukung ios lebih dari 9. Masih jawaban yang bagus, tho.
Eddie
1
Saya sedih melaporkan, bahwa pengaturan ini pada UIButton yang kemudian digunakan untuk UIBarButtonItem tidak menghasilkan perubahan apa pun.
Amelia
Seperti @Amelia sebutkan, itu tidak berfungsi jika Anda menelepon UIBarButtonItem(customView: button), tetapi akan bekerja jika Anda membungkus tombol di dalam beberapa tampilan kosong
tt.Kilew
@ tt.Kilew, menggunakan XCode 8.1 Anda membuatnya berfungsi. Saya mengatur uiButton.semanticContentAttribute = .forceRightToLeft dan memberikan nextButton = UIBarButtonItem (customView: uiButton)
Eugene Biryukov
53

Dalam pembangun antarmuka, Anda dapat mengonfigurasi opsi Edge Insets untuk UIButton, secara terpisah masing-masing dari tiga bagian: konten, gambar, judul

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Xcode 8:

masukkan deskripsi gambar di sini

Gennadiy Ryabkin
sumber
3
sebenarnya jawaban terbaik dalam pandangan saya ini stackoverflow.com/a/39013315/1470374 ))
Gennadiy Ryabkin
25

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

Jawaban asli untuk Swift 2:

Sebuah solusi yang menangani semua perataan horizontal, dengan contoh implementasi Swift. Cukup terjemahkan ke Objective-C jika perlu.

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

Juga perlu dicatat bahwa ia menangani insets gambar & judul dengan cukup baik.

Terinspirasi dari jawaban jasongregori;)

Jean-Baptiste
sumber
1
Solusi ini bekerja untuk saya, namun gambar saya memerlukan beberapa ruang di sekitarnya, jadi saya menambahkan kode berikut: self.contentEdgeInsets = UIEdgeInsetsMake (10.0, 10.0, 10.0, 10.0)
user1354603
1
Saya suka cara ini karena Anda dapat menambah @IBDesignablekelas dan melihatnya terbalik pada waktu desain.
James Toomey
Saya lebih suka solusi ini karena bahkan berfungsi ketika diletakkan di bilah navigasi.
El Horrible
10

Jika ini perlu dilakukan di UIBarButtonItem , pembungkus tambahan harus digunakan.
Ini akan berfungsi

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)

Ini tidak akan berhasil

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

Inilah solusi untuk UIButtondengan konten yang selaras dengan pusat. Kode ini membuat gambar disejajarkan dengan benar dan memungkinkan untuk digunakan imageEdgeInsetsdan titleEdgeInsetsuntuk penentuan posisi yang berharga.

masukkan deskripsi gambar di sini

Subkelas UIButtondengan kelas khusus Anda dan tambahkan:

- (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;
}
Vitaliy Gozhenko
sumber
1
Anda juga dapat menambahkan IBDESIGNABLE ke header kelas untuk menontonnya di storyborad yadi.sk/i/fd6Si-BJqzCFD
Nikolay Shubenkov
6

Karena solusi transformasi tidak berfungsi di iOS 11, saya memutuskan untuk menulis pendekatan baru.

Menyesuaikan tombol semanticContentAttribute memberi kita gambar dengan baik ke kanan tanpa harus menyampaikan jika teks berubah. Karena inilah solusi ideal. Namun saya masih membutuhkan dukungan RTL. Fakta bahwa suatu aplikasi tidak dapat mengubah arah tata letak dalam sesi yang sama menyelesaikan masalah ini dengan mudah.

Dengan itu, itu cukup lurus ke depan.

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

Ekstensi jalan

Menggunakan ekstensi untuk mengatur gambar di sisi kanan dengan offset khusus

   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
    }
}
Musa almatri
sumber
4

Swift -Tambah UiButton dan masukkan baris-baris ini

    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
sumber
3

Membangun solusi elegan Piotr Tomasik: jika Anda ingin memiliki sedikit jarak antara label tombol dan gambar juga, maka sertakan dalam insets tepi Anda sebagai berikut (menyalin kode saya di sini yang berfungsi dengan baik untuk saya):

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

Terima kasih Piotr untuk solusi Anda!

Erik

Erik van der Neut
sumber
@ Lulian: Saya baru-baru ini menggunakan solusi Liau Jian Jie (jawaban yang diterima di sini), dan itu bekerja dengan sangat baik dan merupakan solusi yang sangat elegan.
Erik van der Neut
Itu juga tidak berhasil bagi saya karena itu mengubah perataan teks.
Iulian Onofrei
3

Lakukan sendiri. Xcode10, swift4,

Untuk desain UI terprogram

masukkan deskripsi gambar di sini

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

Nilai inset tepi diterapkan pada persegi panjang untuk mengecilkan atau memperluas area yang ditunjukkan oleh persegi panjang itu. Biasanya, insets tepi digunakan selama tata letak tampilan untuk mengubah bingkai tampilan. Nilai positif menyebabkan frame menjadi inset (atau menyusut) dengan jumlah yang ditentukan. Nilai negatif menyebabkan frame menjadi awal (atau diperluas) dengan jumlah yang ditentukan.

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 )

    }
}

untuk desain StoryBoard UI

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Nazmul Hasan
sumber
apakah ada cara untuk melakukannya dengan lebih elegan?
Zaporozhchenko Oleksandr
2

Tata letak subclassing dan over-ridingSubviews mungkin merupakan cara terbaik Anda.

Dirujuk dari: UIButton iPhone - posisi gambar

FeifanZ
sumber
3
Sama sekali tidak ada masalah untuk subkelas UIButton.
ramah
2

Mengambil jawaban @ Piotr dan membuatnya menjadi ekstensi Swift. Pastikan untuk mengatur gambar dan judul sebelum memanggil ini, sehingga ukuran tombol dengan benar.

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

}

Nick Yap
sumber
2

Opsi cepat yang melakukan apa yang Anda inginkan tanpa bermain dengan inset apa pun:

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
    }

}
Chris
sumber
1

Solusi yang disebutkan di sini berhenti berfungsi, setelah saya mengaktifkan Tata Letak Otomatis . Saya harus membuat sendiri:

Subclass UIButton dan layoutSubviewsmetode override :

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

}

Hasil:

masukkan deskripsi gambar di sini

Lukasz
sumber
1

Swift 3.0 Migration solution diberikan oleh 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
        }
Sourabh Sharma
sumber
1

Saya memutuskan untuk tidak menggunakan tampilan gambar tombol standar karena solusi yang diusulkan untuk memindahkannya terasa dirusak. Ini memberi saya estetika yang diinginkan, dan intuitif untuk memposisikan ulang tombol dengan mengubah batasan:

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

tombol dengan panah kanan

Mark Hennings
sumber
Ini tidak menanggapi ketukan, teks redup tetapi gambar tidak
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
}
Alexander Volkov
sumber
0

Bagaimana dengan Kendala? Tidak seperti semanticContentAttribute, mereka tidak mengubah semantik. Sesuatu seperti ini mungkin:

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

atau di Objective-C:

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

Peringatan: Belum teruji, iOS 9+

rumah kerja batu
sumber
0

Untuk meluruskan gambar di dalam UIButton coba kode di bawah ini

btn.contentHorizontalAlignment = .right
Dhaval H. Nena
sumber
Ini bukan pertanyaan penulis.
Mateusz
0

Setelah mencoba beberapa solusi dari seluruh internet, saya tidak mencapai persyaratan yang tepat. Jadi saya akhirnya menulis kode utilitas khusus. Posting untuk membantu seseorang di masa depan. Diuji pada 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
sumber
0

untuk masalah ini Anda dapat membuat UIView di dalam "label with UIImage view" dan mengatur kelas UIView sebagai UIControl dan membuat IBAction sebagai tuch up in side

masukkan deskripsi gambar di sini

Sushil Vyas
sumber
0

Swift 4 & 5

Ubah arah gambar UIButton (RTL dan 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)
    }
}
Rashid Latif
sumber
Apa Utility?
Byron Coetsee
Saya baru saja menghapus Utilitas, Ini adalah kelas dalam kode saya di mana saya dapat memeriksa apakah bahasa yang dipilih adalah bahasa Arab atau Inggris
Rashid Latif
0

Xcode 11.4 Swift 5.2

Bagi siapa pun yang ingin meniru gaya tombol Kembali dengan chevron seperti ini:

masukkan deskripsi gambar di sini

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

Penerapan:

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

@objc func nextTapped() {
    // your code
}
rbaldwin
sumber
0

Saya akhirnya membuat tombol kustom, yang memungkinkan pengaturan Gambar dari Inspektur. Di bawah ini adalah kode saya:

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

Anda dapat menyesuaikan nilai Gap Padding dari Inspector untuk menyesuaikan jarak antara teks dan gambar.

PS: Menggunakan sebagian kode dari jawaban @ Mark Hennings

Mahendra Liya
sumber