UIButton: bagaimana cara memusatkan gambar dan teks menggunakan imageEdgeInsets dan titleEdgeInsets?

159

Jika saya hanya meletakkan gambar di tombol dan mengatur imageEdgeInsets lebih dekat ke atas, gambar tetap terpusat dan semua berfungsi seperti yang diharapkan:

[button setImage:image forState:UIControlStateNormal];
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, 0.0)];

Jika saya hanya meletakkan teks di tombol dan mengatur titleEdgeInsets lebih dekat ke bawah, teks tetap terpusat dan semua berfungsi seperti yang diharapkan:

[button setTitle:title forState:UIControlStateNormal];
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, 0.0, -30, 0.0)];

Tetapi, jika saya menyatukan 4 baris, teks mengganggu gambar dan keduanya kehilangan perataan tengah.

Semua gambar saya memiliki lebar 30 piksel, dan jika saya menempatkan 30 di parameter kiri UIEdgeInsetMake untuk setTitleEdgeInsets, teks dipusatkan lagi. Masalahnya adalah bahwa gambar tidak pernah terpusat karena tampaknya tergantung pada ukuran button.titleLabel. Saya sudah mencoba banyak perhitungan dengan ukuran tombol, ukuran gambar, ukuran titleLabel dan tidak pernah mendapatkan keduanya secara terpusat sempurna.

Seseorang sudah memiliki masalah yang sama?

reinaldoluckman
sumber

Jawaban:

412

Untuk apa nilainya, inilah solusi umum untuk memposisikan gambar yang berpusat di atas teks tanpa menggunakan angka ajaib. Perhatikan bahwa kode berikut ini sudah usang dan Anda mungkin harus menggunakan salah satu versi yang diperbarui di bawah ini :

// the space between the image and text
CGFloat spacing = 6.0;

// lower the text and push it left so it appears centered 
//  below the image
CGSize imageSize = button.imageView.frame.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
  0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);

// raise the image and push it right so it appears centered
//  above the text
CGSize titleSize = button.titleLabel.frame.size;
button.imageEdgeInsets = UIEdgeInsetsMake(
  - (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

Versi berikut berisi perubahan untuk mendukung iOS 7+ yang telah direkomendasikan dalam komentar di bawah. Saya belum menguji kode ini sendiri, jadi saya tidak yakin seberapa baik kerjanya atau apakah akan rusak jika digunakan di bawah versi iOS sebelumnya.

// the space between the image and text
CGFloat spacing = 6.0;

// lower the text and push it left so it appears centered 
//  below the image
CGSize imageSize = button.imageView.image.size;
button.titleEdgeInsets = UIEdgeInsetsMake(
  0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);

// raise the image and push it right so it appears centered
//  above the text
CGSize titleSize = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}];
button.imageEdgeInsets = UIEdgeInsetsMake(
  - (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

// increase the content height to avoid clipping
CGFloat edgeOffset = fabsf(titleSize.height - imageSize.height) / 2.0;
button.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0);

Versi Swift 5.0

extension UIButton {
  func alignVertical(spacing: CGFloat = 6.0) {
    guard let imageSize = imageView?.image?.size,
      let text = titleLabel?.text,
      let font = titleLabel?.font
    else { return }

    titleEdgeInsets = UIEdgeInsets(
      top: 0.0,
      left: -imageSize.width,
      bottom: -(imageSize.height + spacing),
      right: 0.0
    )

    let titleSize = text.size(withAttributes: [.font: font])
    imageEdgeInsets = UIEdgeInsets(
      top: -(titleSize.height + spacing),
      left: 0.0,
      bottom: 0.0, right: -titleSize.width
    )

    let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0
    contentEdgeInsets = UIEdgeInsets(
      top: edgeOffset,
      left: 0.0,
      bottom: edgeOffset,
      right: 0.0
    )
  }
}
Jesse Crossen
sumber
5
Hebat - terima kasih! Saya pikir banyak jawaban lain tentang "jalan yang sulit" - ini terlihat jauh lebih baik.
Joe D'Andrea
3
Saya menemukan di atas untuk wajan, tetapi saya sama sekali tidak memiliki model mental untuk bagaimana. Adakah yang mendapat tautan ke penjelasan bergambar tentang hal-hal apa saja yang mempengaruhi parameter EdgeInsets? Dan mengapa lebar teks berubah?
Robert Atkins
3
Ini tidak berfungsi saat gambar menyusut agar pas dengan tombol. Tampaknya UIButton (setidaknya di iOS 7) menggunakan image.size, bukan imageView.frame.size untuk perhitungan pemusatan.
Dan Jackson
5
@Hemang dan Dan Jackson, saya memasukkan saran Anda tanpa mengujinya sendiri. Saya merasa agak konyol bahwa saya awalnya menulis ini untuk iOS 4, dan setelah banyak versi ini kami masih harus secara mendasar merekayasa ulang algoritma tata letak Apple untuk mendapatkan fitur yang jelas. Atau setidaknya saya berasumsi belum ada solusi yang lebih baik dari aliran upvotes yang konsisten dan jawaban yang sama meretasnya di bawah ini (tidak ada penghinaan yang dimaksudkan).
Jesse Crossen
5
Di iOS8, saya merasa lebih baik menggunakan button.currentTitledaripada button.titleLabel.textterutama jika teks tombol akan pernah berubah. currentTitledihuni segera, sedangkan titleLabel.textbisa lambat untuk berubah yang dapat menyebabkan insets tidak selaras.
mjangda
59

Menemukan caranya.

Pertama, konfigurasikan teks titleLabel(karena gaya, yaitu tebal, miring, dll). Kemudian, gunakan setTitleEdgeInsetsmempertimbangkan lebar gambar Anda:

[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont boldSystemFontOfSize:10.0]];

// Left inset is the negative of image width.
[button setTitleEdgeInsets:UIEdgeInsetsMake(0.0, -image.size.width, -25.0, 0.0)]; 

Setelah itu, gunakan setTitleEdgeInsetsmempertimbangkan lebar batas teks:

[button setImage:image forState:UIControlStateNormal];

// Right inset is the negative of text bounds width.
[button setImageEdgeInsets:UIEdgeInsetsMake(-15.0, 0.0, 0.0, -button.titleLabel.bounds.size.width)];

Sekarang gambar dan teks akan dipusatkan (dalam contoh ini, gambar muncul di atas teks).

Bersulang.

reinaldoluckman
sumber
3
7 tahun, bung. Benar-benar tidak ingat. Ketika saya bertanya, saya menjawab sendiri (jawaban saya adalah satu-satunya pada saat itu). Saya telah mengubah jawaban yang dipilih ketika penulis jawaban yang dipilih saat ini berfokus pada menghilangkan angka-angka ajaib itu. Jadi, dalam jawaban yang dipilih, Anda dapat mencari tahu apa artinya.
reinaldoluckman
20

Anda dapat melakukannya dengan ekstensi Swift ini, yang sebagian didasarkan pada jawaban Jesse Crossen:

extension UIButton {
  func centerLabelVerticallyWithPadding(spacing:CGFloat) {
    // update positioning of image and title
    let imageSize = self.imageView.frame.size
    self.titleEdgeInsets = UIEdgeInsets(top:0,
                                        left:-imageSize.width,
                                        bottom:-(imageSize.height + spacing),
                                        right:0)
    let titleSize = self.titleLabel.frame.size
    self.imageEdgeInsets = UIEdgeInsets(top:-(titleSize.height + spacing),
                                        left:0,
                                        bottom: 0,
                                        right:-titleSize.width)

    // reset contentInset, so intrinsicContentSize() is still accurate
    let trueContentSize = CGRectUnion(self.titleLabel.frame, self.imageView.frame).size
    let oldContentSize = self.intrinsicContentSize()
    let heightDelta = trueContentSize.height - oldContentSize.height
    let widthDelta = trueContentSize.width - oldContentSize.width
    self.contentEdgeInsets = UIEdgeInsets(top:heightDelta/2.0,
                                          left:widthDelta/2.0,
                                          bottom:heightDelta/2.0,
                                          right:widthDelta/2.0)
  }
}

Ini mendefinisikan suatu fungsi centerLabelVerticallyWithPadding yang mengatur judul dan gambar insets dengan tepat.

Ini juga mengatur contentEdgeInsets, yang saya percaya perlu untuk memastikan itu intrinsicContentSize masih berfungsi dengan benar, yang perlu menggunakan Tata Letak Otomatis.

Saya percaya semua solusi yang mengelompokkan UIButton secara teknis tidak sah, karena Anda tidak seharusnya membuat subkelas kontrol UIKit. Yaitu, secara teori mereka mungkin melanggar rilis di masa depan.

ganggang
sumber
Menguji pada iOS9. Gambar muncul di tengah, tetapi teks muncul di sebelah kiri :(
endavid
13

Sunting: Diperbarui untuk Swift 3

Jika Anda mencari solusi Swift dari jawaban Jesse Crossen, Anda dapat menambahkan ini ke subkelas UIButton:

override func layoutSubviews() {

    let spacing: CGFloat = 6.0

    // lower the text and push it left so it appears centered
    //  below the image
    var titleEdgeInsets = UIEdgeInsets.zero
    if let image = self.imageView?.image {
        titleEdgeInsets.left = -image.size.width
        titleEdgeInsets.bottom = -(image.size.height + spacing)
    }
    self.titleEdgeInsets = titleEdgeInsets

    // raise the image and push it right so it appears centered
    //  above the text
    var imageEdgeInsets = UIEdgeInsets.zero
    if let text = self.titleLabel?.text, let font = self.titleLabel?.font {
        let attributes = [NSFontAttributeName: font]
        let titleSize = text.size(attributes: attributes)
        imageEdgeInsets.top = -(titleSize.height + spacing)
        imageEdgeInsets.right = -titleSize.width
    }
    self.imageEdgeInsets = imageEdgeInsets

    super.layoutSubviews()
}
Thomas Verbeek
sumber
9

Ada beberapa contoh yang bagus di sini, tetapi saya tidak bisa membuat ini berfungsi dalam semua kasus ketika juga berurusan dengan beberapa baris teks (pembungkus teks). Untuk akhirnya berhasil, saya menggabungkan beberapa teknik:

  1. Saya menggunakan contoh Jesse Crossen di atas. Namun, saya memperbaiki masalah ketinggian teks dan saya menambahkan kemampuan untuk menentukan margin teks horizontal. Margin berguna ketika memungkinkan teks untuk membungkus sehingga tidak menyentuh tepi tombol:

    // the space between the image and text
    CGFloat spacing = 10.0;
    float   textMargin = 6;
    
    // get the size of the elements here for readability
    CGSize  imageSize   = picImage.size;
    CGSize  titleSize   = button.titleLabel.frame.size;
    CGFloat totalHeight = (imageSize.height + titleSize.height + spacing);      // get the height they will take up as a unit
    
    // lower the text and push it left to center it
    button.titleEdgeInsets = UIEdgeInsetsMake( 0.0, -imageSize.width +textMargin, - (totalHeight - titleSize.height), +textMargin );   // top, left, bottom, right
    
    // the text width might have changed (in case it was shortened before due to 
    // lack of space and isn't anymore now), so we get the frame size again
    titleSize = button.titleLabel.bounds.size;
    
    button.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + spacing), 0.0, 0.0, -titleSize.width );     // top, left, bottom, right        
  2. Pastikan Anda menyiapkan label teks untuk dibungkus

    button.titleLabel.numberOfLines = 2; 
    button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
    button.titleLabel.textAlignment = UITextAlignmentCenter;
  3. Ini sebagian besar akan berfungsi sekarang. Namun, saya memiliki beberapa tombol yang tidak akan membuat gambar mereka dengan benar. Gambar dipindahkan ke jauh ke kanan atau kiri (tidak terpusat). Jadi saya menggunakan teknik menimpa tata letak UIButton untuk memaksa imageView menjadi terpusat.

    @interface CategoryButton : UIButton
    @end
    
    @implementation CategoryButton
    
    - (void)layoutSubviews
    {
        // Allow default layout, then center imageView
        [super layoutSubviews];
    
        UIImageView *imageView = [self imageView];
        CGRect imageFrame = imageView.frame;
        imageFrame.origin.x = (int)((self.frame.size.width - imageFrame.size.width)/ 2);
        imageView.frame = imageFrame;
    }
    @end
Tod Cunningham
sumber
Sepertinya ini adalah solusi yang baik, namun bukankah seharusnya button.titleLabel.numberOfLines menjadi 0 sehingga dapat sebanyak mungkin garis yang diinginkan?
Ben Lachman
Dalam kasus saya, saya hanya ingin dua baris. Jika tidak, gambar akan mengalami masalah ukuran keseluruhan tombol.
Tod Cunningham
9

Saya membuat metode untuk jawaban @ TodCunningham

 -(void) AlignTextAndImageOfButton:(UIButton *)button
 {
   CGFloat spacing = 2; // the amount of spacing to appear between image and title
   button.imageView.backgroundColor=[UIColor clearColor];
   button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
   button.titleLabel.textAlignment = UITextAlignmentCenter;
   // get the size of the elements here for readability
   CGSize imageSize = button.imageView.frame.size;
   CGSize titleSize = button.titleLabel.frame.size;

  // lower the text and push it left to center it
  button.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, - (imageSize.height   + spacing), 0.0);

  // the text width might have changed (in case it was shortened before due to 
  // lack of space and isn't anymore now), so we get the frame size again
   titleSize = button.titleLabel.frame.size;

  // raise the image and push it right to center it
  button.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, -     titleSize.width);
 }
Bekir Onat Akin
sumber
7

Diperbarui untuk Xcode 11+

Insets yang dijelaskan dalam jawaban asli saya telah dipindahkan ke inspektur ukuran di versi Xcode yang lebih baru. Saya tidak 100% jelas tentang kapan saklar terjadi tetapi pembaca harus meninjau inspektur ukuran jika informasi inset tidak ditemukan dalam atribut inspektur. Di bawah ini adalah contoh layar inset baru (terletak di bagian atas atribut ukuran inspektur pada 11.5).

insets_moved_to_size_inspector

Jawaban Asli

Tidak ada yang salah dengan jawaban lainnya, namun saya hanya ingin mencatat bahwa perilaku yang sama dapat dicapai secara visual dalam Xcode menggunakan nol baris kode. Solusi ini berguna jika Anda tidak memerlukan nilai yang dihitung atau sedang membangun dengan storyboard / xib (jika tidak solusi lain berlaku).

Catatan - Saya mengerti bahwa pertanyaan OP adalah salah satu yang memerlukan kode. Saya hanya memberikan jawaban ini untuk kelengkapan dan sebagai alternatif logis bagi mereka yang menggunakan storyboard / xibs.

Untuk memodifikasi jarak pada tampilan gambar, judul, dan konten dari suatu tombol menggunakan insets tepi Anda dapat memilih tombol / kontrol dan membuka pemeriksa atribut. Gulir ke bawah ke arah tengah inspektur dan temukan bagian untuk Edge insets.

insets ujung

Seseorang juga dapat mengakses dan memodifikasi insets tepi spesifik untuk tampilan judul, gambar atau konten.

pilihan menu

Tommie C.
sumber
Yang tidak saya mengerti adalah mengapa saya sepertinya tidak bisa memasukkan angka negatif di storyboard untuk beberapa nilai.
Daniel T.
Apakah ini berfungsi untuk versi cepat yang lebih baru? Saya tidak dapat menemukan atribut Edge di mana pun
brockhampton
@brockhampton - lihat jawaban terbaru untuk lokasi baru
Tommie C.
6

Jangan melawan sistem. Jika tata letak Anda menjadi terlalu rumit untuk dikelola menggunakan Interface Builder + mungkin beberapa kode konfigurasi sederhana, lakukan tata letak secara manual dengan cara yang lebih sederhana menggunakanlayoutSubviews - itulah gunanya! Yang lainnya akan berarti peretasan.

Buat subkelas UIButton dan timpa layoutSubviewsmetodenya untuk menyelaraskan teks & gambar Anda secara terprogram. Atau gunakan sesuatu seperti https://github.com/nickpaulson/BlockKit/blob/master/Source/UIView-BKAdditions.h sehingga Anda dapat mengimplementasikan layoutSubviews menggunakan blok.

Steven Kramer
sumber
6

Subkelas UIButton

- (void)layoutSubviews {
    [super layoutSubviews];
    CGFloat spacing = 6.0;
    CGSize imageSize = self.imageView.image.size;
    CGSize titleSize = [self.titleLabel sizeThatFits:CGSizeMake(self.frame.size.width, self.frame.size.height - (imageSize.height + spacing))];
    self.imageView.frame = CGRectMake((self.frame.size.width - imageSize.width)/2, (self.frame.size.height - (imageSize.height+spacing+titleSize.height))/2, imageSize.width, imageSize.height);
    self.titleLabel.frame = CGRectMake((self.frame.size.width - titleSize.width)/2, CGRectGetMaxY(self.imageView.frame)+spacing, titleSize.width, titleSize.height);
}
Alex
sumber
6

Jawaban Jesse Crossen yang diperbarui untuk Swift 4 :

extension UIButton {
    func alignVertical(spacing: CGFloat = 6.0) {
        guard let imageSize = self.imageView?.image?.size,
            let text = self.titleLabel?.text,
            let font = self.titleLabel?.font
            else { return }
        self.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)
        let labelString = NSString(string: text)
        let titleSize = labelString.size(withAttributes: [kCTFontAttributeName as NSAttributedStringKey: font])
        self.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0.0, bottom: 0.0, right: -titleSize.width)
        let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
        self.contentEdgeInsets = UIEdgeInsets(top: edgeOffset, left: 0.0, bottom: edgeOffset, right: 0.0)
    }
}

Gunakan cara ini:

override func viewDidLayoutSubviews() {
    button.alignVertical()
}
Doci
sumber
Setelah berjam-jam. Ini adalah satu-satunya hal yang berhasil :)
Harry Blue
4

Dengan potongan kode ini, Anda akan mendapatkan sesuatu seperti ini judul dan penyelarasan gambar

extension UIButton {
    func alignTextUnderImage() {
        guard let imageView = imageView else {
                return
        }
        self.contentVerticalAlignment = .Top
        self.contentHorizontalAlignment = .Center
        let imageLeftOffset = (CGRectGetWidth(self.bounds) - CGRectGetWidth(imageView.bounds)) / 2//put image in center
        let titleTopOffset = CGRectGetHeight(imageView.bounds) + 5
        self.imageEdgeInsets = UIEdgeInsetsMake(0, imageLeftOffset, 0, 0)
        self.titleEdgeInsets = UIEdgeInsetsMake(titleTopOffset, -CGRectGetWidth(imageView.bounds), 0, 0)
    }
}
Bohdan Savych
sumber
2
Saya menulis ekstensi kecil untuk memposisikan gambar dan teks di dalam tombol. Jika Anda tertarik, ini adalah kode sumber. github.com/sssbohdan/ButtonAlignmentExtension/blob/master/…
Bohdan Savych
4

Ekstensi UIButton dengan sintaks Swift 3+ :

extension UIButton {
    func alignImageAndTitleVertically(padding: CGFloat = 6.0) {
        let imageSize: CGSize = imageView!.image!.size
        titleEdgeInsets = UIEdgeInsetsMake(0.0, -imageSize.width, -(imageSize.height + padding), 0.0)
        let labelString = NSString(string: titleLabel!.text!)
        let titleSize = labelString.size(attributes: [NSFontAttributeName: titleLabel!.font])
        self.imageEdgeInsets = UIEdgeInsetsMake(-(titleSize.height + padding), 0.0, 0.0, -titleSize.width)
        let edgeOffset = abs(titleSize.height - imageSize.height) / 2.0;
        self.contentEdgeInsets = UIEdgeInsetsMake(edgeOffset, 0.0, edgeOffset, 0.0)
    }
}

Jawaban asli: https://stackoverflow.com/a/7199529/3659227

Maverick
sumber
3

Hanya sedikit perubahan pada jawaban Jesse Crossen yang membuatnya bekerja sempurna untuk saya:

dari pada:

CGSize titleSize = button.titleLabel.frame.size;

Saya telah menggunakan ini:

CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName:button.titleLabel.font}];
Cesar
sumber
Selamat datang di SO! Alih-alih menambahkan jawaban terpisah (untuk perubahan kecil), Anda dapat menulis ini langsung ke Jesse sehingga ia dapat memeriksa dan memperbarui jawaban [diterima] dengan benar (jika perlu).
Hemang
3

Menggunakan button.titleLabel.frame.size.widthberfungsi dengan baik hanya selama label cukup pendek untuk tidak terpotong. Ketika teks label diposisikan terpotong tidak bekerja sekalipun. Pengambilan

CGSize titleSize = [[[button titleLabel] text] sizeWithFont:[[button titleLabel] font]];

bekerja untuk saya bahkan ketika teks label terpotong.

dezember
sumber
Anda memiliki salah ketik.
Bhimbim
2

Saya melihat jawaban yang ada tetapi saya juga menemukan bahwa pengaturan bingkai tombol adalah langkah pertama yang penting.

Berikut adalah fungsi yang saya gunakan yang menangani ini:

const CGFloat kImageTopOffset   = -15;
const CGFloat kTextBottomOffset = -25;

+ (void) centerButtonImageTopAndTextBottom: (UIButton*)         button 
                                     frame: (CGRect)            buttonFrame
                                      text: (NSString*)         textString
                                 textColor: (UIColor*)          textColor
                                      font: (UIFont*)           textFont
                                     image: (UIImage*)          image
                                  forState: (UIControlState)    buttonState
{
    button.frame = buttonFrame;

    [button setTitleColor: (UIColor*)       textColor
                 forState: (UIControlState) buttonState];

    [button setTitle: (NSString*) textString
            forState: (UIControlState) buttonState ];


    [button.titleLabel setFont: (UIFont*) textFont ];

    [button setTitleEdgeInsets: UIEdgeInsetsMake( 0.0, -image.size.width, kTextBottomOffset,  0.0)]; 

    [button setImage: (UIImage*)       image 
            forState: (UIControlState) buttonState ];

    [button setImageEdgeInsets: UIEdgeInsetsMake( kImageTopOffset, 0.0, 0.0,- button.titleLabel.bounds.size.width)];
}
Bamaco
sumber
2

Atau Anda bisa menggunakan kategori ini:

@interface UIButton (VerticalLayout)  

- (void)centerVerticallyWithPadding:(float)padding;  
- (void)centerVertically;  

@end  


@implementation UIButton (VerticalLayout)  

- (void)centerVerticallyWithPadding:(float)padding 
{      
    CGSize imageSize = self.imageView.frame.size;  
    CGSize titleSize = self.titleLabel.frame.size;  

    CGFloat totalHeight = (imageSize.height + titleSize.height + padding);  

    self.imageEdgeInsets = UIEdgeInsetsMake(- (totalHeight - imageSize.height),
                                            0.0f,
                                            0.0f,
                                            - titleSize.width);

    self.titleEdgeInsets = UIEdgeInsetsMake(0.0f,
                                            - imageSize.width,
                                            - (totalHeight - titleSize.height),
                                            0.0f);

}


- (void)centerVertically
{  
    const CGFloat kDefaultPadding = 6.0f;

    [self centerVerticallyWithPadding:kDefaultPadding];  
}  


@end
RaffAl
sumber
1
Ini tidak akan berfungsi dengan font khusus. Dari iOS7 +,CGSize titleSize = [button.titleLabel.text sizeWithAttributes: @{NSFontAttributeName: button.titleLabel.font}];
Hemang
1

Kasing kasus saya membuat inset tidak dapat dikelola:

  1. gambar latar belakang pada tombol tetap konsisten
  2. teks dan gambar dinamis berubah di mana panjang string dan ukuran gambar bervariasi

Inilah yang akhirnya saya lakukan dan saya cukup senang dengan itu:

  • Buat tombol pada storyboard dengan gambar latar belakang (lingkaran bulat dengan blur dan warna).

  • Deklarasikan UIImageView di kelas saya:

    @implementation BlahViewController {
        UIImageView *_imageView;
    }
  • Buat contoh tampilan gambar di init:

    -(id)initWithCoder:(NSCoder *)aDecoder {
        self = [super initWithCoder:aDecoder];
        if (self) {
            _imageView = [[UIImageView alloc] initWithCoder:aDecoder];
         }
         return self;
     }
  • Di viewDidLoad tambahkan layer baru ke tombol untuk tampilan gambar kami dan atur perataan teks:

    [self.btn addSubview:_imageView];
    [self.btn.titleLabel setTextAlignment:NSTextAlignmentCenter];
  • Dalam metode klik tombol tambahkan gambar overlay yang saya pilih ke tampilan gambar, ukurannya agar sesuai dengan gambar dan pusatkan pada tombol tetapi bergerak ke atas 15 sehingga saya dapat menempatkan teks offset di bawahnya:

    [_imageView setImage:[UIImage imageNamed:@"blahImageBlah]];
    [_imageView sizeToFit];
    _imageView.center = CGPointMake(ceilf(self.btn.bounds.size.width / 2.0f),
             ceilf((self.btn.bounds.size.height / 2.0f) - 15));
    [self.btn setTitle:@"Some new text" forState:UIControlStateNormal];

Catatan: ceilf () penting untuk memastikannya pada batas piksel untuk kualitas gambar.

Oliver Dungey
sumber
1
Jelas pendekatan yang lebih baik untuk kasus penggunaan saya juga karena saya menambahkan tombol ke tampilan tumpukan.
valeCocoa
0

Dengan asumsi bahwa Anda ingin kedua teks dan gambar dipusatkan secara horizontal, gambar di atas teks: Pusatkan teks dari pembangun antarmuka dan tambahkan inset atas (membuat ruang untuk gambar). (biarkan inset kiri ke 0). Gunakan pembangun antarmuka untuk memilih gambar - posisi sebenarnya akan ditetapkan dari kode, jadi jangan khawatir bahwa segala sesuatu tidak akan terlihat baik di IB. Tidak seperti jawaban lain di atas, ini benar-benar berfungsi pada semua versi ios yang saat ini didukung (5,6 dan 7).

Dalam kode, cukup buang ImageView tombol (dengan mengatur gambar tombol ke nol) setelah mengambil gambar (ini juga akan secara otomatis menempatkan teks di tengah, jika perlu dibungkus). Kemudian instantiate ImageView Anda sendiri dengan ukuran dan gambar bingkai yang sama dan posisikan di tengah.

Dengan cara ini Anda masih dapat memilih gambar dari pembangun antarmuka (meskipun tidak akan disejajarkan dalam IB seperti dalam simulator, tetapi sekali lagi, solusi lain tidak kompatibel di semua versi ios yang didukung)

Radu Simionescu
sumber
0

Saya berjuang untuk menyelesaikan ini karena saya tidak bisa mendapatkan ukuran gambar dan lebar teks pada konstruktor pandangan saya. Dua perubahan kecil pada jawaban Jesse bekerja untuk saya:

CGFloat spacing = 3;
self.titleEdgeInsets = UIEdgeInsetsMake(0.0, - image.size.width, - (image.size.height + spacing), 0.0);
CGSize titleSize = [name sizeWithAttributes:@{NSFontAttributeName:self.titleLabel.font}];
self.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);

Perubahannya adalah:

  • Menggunakan [NSString sizeWithAttributes] untuk mendapatkan lebar teks;
  • Dapatkan ukuran gambar langsung di UIImagebukanUIImageView
saulobrito
sumber
0

Ini berfungsi baik untuk saya, untuk beberapa tombol, dengan lebar gambar berbeda dan panjang judul berbeda:

Subkelas UIButton

override func layoutSubviews() {
    super.layoutSubviews()

    if let image = imageView?.image {

        let margin = 30 - image.size.width / 2
        let titleRect = titleRectForContentRect(bounds)
        let titleOffset = (bounds.width - titleRect.width - image.size.width - margin) / 2


        contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
            imageEdgeInsets = UIEdgeInsetsMake(0, margin, 0, 0)
            titleEdgeInsets = UIEdgeInsetsMake(0, (bounds.width - titleRect.width -  image.size.width - margin) / 2, 0, 0)
    }

}
Remy Virin
sumber
0

Bekerja dengan baik untuk ukuran tombol 80x80 piksel.

[self.leftButton setImageEdgeInsets:UIEdgeInsetsMake(0, 10.0, 20.0, 10.0)];    
[self.leftButton setTitleEdgeInsets:UIEdgeInsetsMake(60, -75.0, 0.0, 0.0)];
BADRI
sumber
0

Saya melakukan beberapa penyesuaian untuk membuat gambar sejajar di tengah horizontal:

// the space between the image and text
        let spacing = CGFloat(36.0);

        // lower the text and push it left so it appears centered
        //  below the image
        let imageSize = tutorialButton.imageView!.frame.size;
        tutorialButton.titleEdgeInsets = UIEdgeInsetsMake(
            0, -CGFloat(imageSize.width), -CGFloat(imageSize.height + spacing), 0.0);

        // raise the image and push it right so it appears centered
        //  above the text
        let titleSize = tutorialButton.titleLabel!.frame.size;
        tutorialButton.imageEdgeInsets = UIEdgeInsetsMake(
            -CGFloat(titleSize.height + spacing), CGFloat((tutorialButton.frame.width - imageSize.width) / 2), 0.0, -CGFloat(titleSize.width));
Nguyễn Thanh Khiêm
sumber
0

apakah wajib menggunakan insets edge? Jika tidak, Anda dapat mencoba memposisikan hormat ke tampilan orang tua pusat

extension UIButton 
{
    func centerImageAndTextVerticaAlignment(spacing: CGFloat) 
    {
        var titlePoint : CGPoint = convertPoint(center, fromView:superview)
        var imageViewPoint : CGPoint = convertPoint(center, fromView:superview)
        titlePoint.y += ((titleLabel?.size.height)! + spacing)/2
        imageViewPoint.y -= ((imageView?.size.height)! + spacing)/2
        titleLabel?.center = titlePoint
        imageView?.center = imageViewPoint

    }
}
Rodrigo Birriel
sumber
Pertanyaannya secara eksplisit menanyakan penggunaan imageEdgeInsets dan titleEdgeInsets sehingga kemungkinan hal itu wajib
Tibrogargan
0

Anda perlu memindahkan gambar ke kanan dengan lebar teks. Kemudian pindahkan teks ke kiri dengan lebar gambar.

UIEdgeInsets imageEdgeInsets = self.remoteCommandsButtonLights.imageEdgeInsets;
imageEdgeInsets.left = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName:[button.titleLabel font]}].width;
imageEdgeInsets.bottom = 14.0;
button.imageEdgeInsets = imageEdgeInsets;

UIEdgeInsets titleEdgeInsets = self.remoteCommandsButtonLights.titleEdgeInsets;
titleEdgeInsets.left = -button.currentImage.size.width;
titleEdgeInsets.top = 20.0;
button.titleEdgeInsets = titleEdgeInsets;

Kemudian sesuaikan inset atas dan bawah untuk menyesuaikan sumbu Y. Ini mungkin bisa dilakukan secara terprogram juga, tetapi harus konstan untuk ukuran gambar Anda. Sedangkan inset sumbu-X perlu diubah berdasarkan ukuran label teks di setiap tombol.

pkamb
sumber
0

Tambahkan kode ini di ekstensi Swift 4.2

 func moveImageLeftTextCenter(imagePadding: CGFloat = 30.0){
    guard let imageViewWidth = self.imageView?.frame.width else{return}
    guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
    self.contentHorizontalAlignment = .left
    imageEdgeInsets = UIEdgeInsets(top: 0.0, left: imagePadding - imageViewWidth / 2, bottom: 0.0, right: 0.0)
    titleEdgeInsets = UIEdgeInsets(top: 0.0, left: (bounds.width - titleLabelWidth) / 2 - imageViewWidth, bottom: 0.0, right: 0.0)
}
func moveImageRIghtTextCenter(imagePadding: CGFloat = 30.0){
    guard let imageViewWidth = self.imageView?.frame.width else{return}
    guard let titleLabelWidth = self.titleLabel?.intrinsicContentSize.width else{return}
    self.contentHorizontalAlignment = .right
    imageEdgeInsets = UIEdgeInsets(top: 0.0, left:0.0 , bottom: 0.0, right: imagePadding - imageViewWidth / 2)
    titleEdgeInsets = UIEdgeInsets(top: 0.0, left:0.0 , bottom: 0.0, right:(bounds.width - titleLabelWidth) / 2 - imageViewWidth)
}
Shahzaib Maqbool
sumber
0

Hanya dengan memasukkan 2 sen saya, ini berhasil bagi saya:

extension UIButton {
  public func centerImageAndTextVertically(spacing: CGFloat) {
    layoutIfNeeded()
    let contentFrame = contentRect(forBounds: bounds)
    let imageFrame = imageRect(forContentRect: contentFrame)
    let imageLeftInset = bounds.size.width * 0.5 - imageFrame.size.width * 0.5
    let imageTopInset = -(imageFrame.size.height + spacing * 0.5)
    let titleFrame = titleRect(forContentRect: contentFrame)
    let titleLeftInset = ((bounds.size.width - titleFrame.size.width) * 0.5) - imageFrame.size.width
    let titleTopInmset = titleFrame.size.height + spacing * 0.5
    imageEdgeInsets = UIEdgeInsets(top: imageTopInset, left: imageLeftInset, bottom: 0, right: 0)
    titleEdgeInsets = UIEdgeInsets(top: titleTopInmset, left: titleLeftInset, bottom: 0, right: 0)
  }
}
Chris Wooden
sumber