Bir UIButton'a çok satırlı metni nasıl eklersiniz?


368

Takip koduna sahibim...

UILabel *buttonLabel = [[UILabel alloc] initWithFrame:targetButton.bounds];
buttonLabel.text = @"Long text string";
[targetButton addSubview:buttonLabel];
[targetButton bringSubviewToFront:buttonLabel];

... fikir, düğme için çok satırlı metne sahip olabileceğim, ancak metnin her zaman arka plan tarafından gizlendiğidir. Düğmenin alt görüntülerini gösteren bir günlük çağrısı, UILabel'in eklendiğini gösterir, ancak metnin kendisi görülemez. Bu UIButton'da bir hata mı yoksa yanlış bir şey mi yapıyorum?


7
button.titleLabel?.numberOfLines = 0
ma11hew28

2
Bu çok çok eski QA için not, modern Xcode ÇOK SADECE, "KATKILI METİN" SEÇİN ve sonra önemsiz, "karakter sarma" seçin.
Fattie

Benzer bir sorunun güncellenmiş cevabına da bakınız .
ToolmakerSteve

düğme metni için bu cevaba bakın (çok satırlı, uygun genişlik, uygun yükseklik) stackoverflow.com/a/59211399/7523163
Hamid Reza Ansari

Yanıtlar:


676

İOS 6 ve üstü sürümlerde, birden fazla satıra izin vermek için aşağıdakileri kullanın:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
// you probably want to center it
button.titleLabel.textAlignment = NSTextAlignmentCenter; // if you want to 
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];

İOS 5 ve önceki sürümlerde, birden fazla satıra izin vermek için aşağıdakileri kullanın:

button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
// you probably want to center it
button.titleLabel.textAlignment = UITextAlignmentCenter;
[button setTitle: @"Line1\nLine2" forState: UIControlStateNormal];

2017, iOS9 ileri için ,

genellikle şu iki şeyi yapın:

  1. seçim "Attributed Metin"
  2. "Satır Kesme" açılır penceresinde "Sözcük Kaydırma" yı seçin

5
Bu atamaların iOS 6'da kaldırıldığını lütfen unutmayın. Güncellenmiş sözdizimi için @NiKKi'nin aşağıdaki cevabına bakın.
Aaron Brager

6
Sadece insanlar biliyor: NSAttributedString
The dude

29
Aslında button.titleLabel.numberOfLines = 0 ekleyin; Bu, çizgileri sınırsız hale getirecektir. Ve button.titleLabel.textAlignment = NSTextAlignmentLeft; başlık varsayılan olarak ortalandığı için iki yana yaslanmış metin bırakmak istiyorsanız.
RyJ

4
Hızlıbutton.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
Robert

1
Hızlı çözüm için @Robert'e teşekkürler. Ayrıca çıkarımı kullanmak ve ihmal Can NSLineBreakModeşöyle: button.titleLabel?.lineBreakMode = .ByWordWrapping.
mjswensen

145

Seçilen cevap doğrudur, ancak Interface Builder'da bu tür bir şey yapmayı tercih ederseniz şunları yapabilirsiniz:

pic


58
Bu cevabı yazdığım 24 yaşındaki benliğime 28 yaşındaki benlik için teşekkürler.
Adam Waite

5
Ve Arayüz Oluşturucu sadece kurulum ile kalmak için tek belirlesin titleLabel.textAlignmentile Numberdeğerli 1içinde User Defined Runtime Attributedyapmak metin merkezli
AnthoPak

2
24 yaşındaki kendimden 28 yaşındaki kendinize teşekkürler!
Daniel Springer

59

Başlığı birden çok çizgiyle ortalanmış bir düğme eklemek istiyorsanız, Arayüz Oluşturucunuzun düğme için ayarlarını yapın:

[ buraya]


Bunu nasıl başaracağınıza ilişkin metinsel bir açıklama ekleyebilir misiniz? Bir görüntü harika, ancak kullanılamaz hale gelirse cevabınız işe yaramaz.
Rory McCrossan

1
@RoryMcCrossan Merhaba, yukarıya bir resim ekledim. Görebilir misin? Lütfen unutmayın, Xcode 7 hala hatalıdır, bu nedenle düğme başlığı kaybolabilir. Ancak, bir kez uygulamayı çalıştırmak istediğiniz sonucu alırsınız.
user5440039

2
Bu konudaki en iyi cevap aslında. Hemen çalışır ve IB'den ortalanmış metin gösterir. Teşekkürler!
RainCast

@ user5440039 Harika yanıt için teşekkürler. Metinsel bir açıklama eklemenize gerek yoktur.
Fattie

54

IOS 6 için:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;

Gibi

UILineBreakModeWordWrap and UITextAlignmentCenter

IOS 6'dan itibaren kullanımdan kaldırılmıştır ..


İçinde NSText.hde Foundationhiçbir orada ilave kullanımdan kaldırılmıştır. 6.0 sürümünden kullanılabilir ancak kullanımdan kaldırılmamıştır.
Alex Cio

button.titleLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping button.titleLabel?.textAlignment = NSTextAlignment.Center
Hızlıca

30

Roger Nolan'ın önerisini yeniden ifade etmek için, ancak açık kodla, bu genel çözümdür:

button.titleLabel?.numberOfLines = 0

21

SWIFT 3

button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center  
button.setTitle("Button\nTitle",for: .normal)

13

Xcode 9.3'te aşağıdaki gibi storyboard kullanarak yapabilirsiniz ,

resim açıklamasını buraya girin

Düğme başlığı metnini ayarlamanız gerekiyor Merkeze hizalama

button.titleLabel?.textAlignment = .center

Başlık metnini aşağıdaki gibi yeni satır (\ n) ile ayarlamanıza gerek yoktur,

button.setTitle("Good\nAnswer",for: .normal)

Sadece başlığı ayarlayın,

button.setTitle("Good Answer",for: .normal)

İşte sonuç,

resim açıklamasını buraya girin


myButton.titleLabel.textAlignment = NSTextAlignmentCenterifadesi de gereklidir.
tounaobun

11

Çok daha kolay bir yol var:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(İOS 3 ve sonraki sürümleri için düzenleme :)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

4
UIButton.lineBreakMode 3.0'da kullanımdan kaldırıldı, bu yüzden artık iyi bir seçenek değil.
Christopher Pickslay

2
lineBreakMode yalnızca UIButton'un doğrudan özelliği olarak kullanımdan kaldırılmıştır. Biz "titleLabel yerine lineBreakMode özelliğini kullanın." Valerii'nin cevabını buna göre düzenledim. Hala iyi bir seçenek.
Wienke

11

Otomatik düzen ile iOS7'de sola hizala:

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentLeft;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;

9

Sonucun böyleydi çok satırlı etkinleştirdikten sonra, otomatik düzen ile bir sorunu vardı: böylece boyut düğmesi boyutunu etkilemez ben ekledim dayanan , 10 yaşındayken bu durumda contentEdgeInsets içinde ((10, 10, 10 ) aradıktan sonra : umarım size yardımcı olur (hızlı 5.0):
resim açıklamasını buraya girin
titleLabel
ConstraintscontentEdgeInsets
makeMultiLineSupport()
resim açıklamasını buraya girin

extension UIButton {

    func makeMultiLineSupport() {
        guard let titleLabel = titleLabel else {
            return
        }
        titleLabel.numberOfLines = 0
        titleLabel.setContentHuggingPriority(.required, for: .vertical)
        titleLabel.setContentHuggingPriority(.required, for: .horizontal)
        addConstraints([
            .init(item: titleLabel,
                  attribute: .top,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .top,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.top),
            .init(item: titleLabel,
                  attribute: .bottom,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .bottom,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.bottom),
            .init(item: titleLabel,
                  attribute: .left,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .left,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.left),
            .init(item: titleLabel,
                  attribute: .right,
                  relatedBy: .greaterThanOrEqual,
                  toItem: self,
                  attribute: .right,
                  multiplier: 1.0,
                  constant: contentEdgeInsets.right)
            ])
    }

}

Hızlı 5'te mükemmel çalışır. Ayrıca düğmedeki metni ortalamak için işlevimi ekledim. func centerTextInButton () {guard let titleLabel = titleLabel else {return} titleLabel.textAlignment = .center}
ShadeToD 18:19

Teşekkür ederim. Bu çok iyi bir çözüm.
Echelon

Kısıtlama eklemenin gerekli olmadığını gördüm, sadece lineBreakMode / textAlignment / numberOfLines ayarlandıktan sonra metni ayarlayın. Üst ve alt iç metinler için titleEdgeInsets'i de ayarlayın.
Bill Chan

@BillChan ne yazık ki bu her durumda işe yaramıyor
Amir Khorsandi

7

Her şeyden önce, UIButton'un içinde zaten bir UILabel olduğunu bilmelisiniz. Düğmesini kullanarak ayarlayabilirsiniz –setTitle:forState:.

Örneğinizle ilgili sorun, UILabel'ın numberOfLinesözelliğini varsayılan 1 değeri dışında bir değere ayarlamanız gerektiğidir. Ayrıca lineBreakModeözelliği de gözden geçirmelisiniz.


Title özelliğinin farkındayım, ancak anlayabildiğim kadarıyla, birden fazla satır kullanması imkansız, bu nedenle bu yaklaşım. BackgroundImage'ı devre dışı bırakırsam, UILabel'im ortaya çıkar, bu da bana bringSubviewToFront veya UIButton'un kendisinde bir hata olduğunu gösterir.
Owain Hunt

4

Xcode 4'ün storyboard'unu kullananlar için, düğmeyi tıklayabilirsiniz ve sağ taraftaki Özellikler bölmesi altındaki Özellikler bölmesinde, Satır Kesmesi için bir seçenek görürsünüz. Word Wrap'ı seçin ve gitmek için iyi olmalısınız.


4

Buradaki yanıtlar, programlı olarak çok satırlı düğme başlığına nasıl ulaşılacağını anlatır.

Sadece film şeridi kullanıyorsanız, bir düğme başlığı alanında yeni bir satırı zorlamak için [Ctrl + Enter] yazabileceğinizi eklemek istedim.

HTH



3

Brent'in UILabel unvanını kardeş görüşü olarak koyma fikrine gelince, bana çok iyi bir fikir gibi gelmiyor. UIButton'un görüşünden geçemediği dokunma olayları nedeniyle UILabel ile etkileşim sorunlarını düşünmeye devam ediyorum.

Öte yandan, UIButton'un alt görünümü olarak bir UILabel ile, dokunma olaylarının her zaman UILabel'ın denetimine yayılacağını bilmek oldukça rahatım.

Bu yaklaşımı benimsedim ve backgroundImage ile bildirilen sorunlardan hiçbirini fark etmedim. Bu kodu bir UIButton alt sınıfının -titleRectForContentRect: dosyasına ekledim, ancak kod aynı zamanda UIButton denetiminin çizim rutinine de yerleştirilebilir, bu durumda kendinize tüm referansları UIButton değişkeniyle değiştirirsiniz.

#define TITLE_LABEL_TAG 1234

- (CGRect)titleRectForContentRect:(CGRect)rect
{   
    // define the desired title inset margins based on the whole rect and its padding
    UIEdgeInsets padding = [self titleEdgeInsets];
    CGRect titleRect = CGRectMake(rect.origin.x    + padding.left, 
                                  rect.origin.x    + padding.top, 
                                  rect.size.width  - (padding.right + padding.left), 
                                  rect.size.height - (padding.bottom + padding].top));

    // save the current title view appearance
    NSString *title = [self currentTitle];
    UIColor  *titleColor = [self currentTitleColor];
    UIColor  *titleShadowColor = [self currentTitleShadowColor];

    // we only want to add our custom label once; only 1st pass shall return nil
    UILabel  *titleLabel = (UILabel*)[self viewWithTag:TITLE_LABEL_TAG];


    if (!titleLabel) 
    {
        // no custom label found (1st pass), we will be creating & adding it as subview
        titleLabel = [[UILabel alloc] initWithFrame:titleRect];
        [titleLabel setTag:TITLE_LABEL_TAG];

        // make it multi-line
        [titleLabel setNumberOfLines:0];
        [titleLabel setLineBreakMode:UILineBreakModeWordWrap];

        // title appearance setup; be at will to modify
        [titleLabel setBackgroundColor:[UIColor clearColor]];
        [titleLabel setFont:[self font]];
        [titleLabel setShadowOffset:CGSizeMake(0, 1)];
        [titleLabel setTextAlignment:UITextAlignmentCenter];

        [self addSubview:titleLabel];
        [titleLabel release];
    }

    // finally, put our label in original title view's state
    [titleLabel setText:title];
    [titleLabel setTextColor:titleColor];
    [titleLabel setShadowColor:titleShadowColor];

    // and return empty rect so that the original title view is hidden
    return CGRectZero;
}

Vaktim yaptı ve bu konuda daha fazla biraz yazdım buraya . Orada da, daha kısa bir çözüme işaret ediyorum, ancak tüm senaryolara tam olarak uymuyor ve bazı özel görüşlerin hacklenmesini içeriyor. Ayrıca orada, kullanıma hazır bir UIButton alt sınıfı indirebilirsiniz.


3

İOS 6'da otomatik düzen kullanıyorsanız preferredMaxLayoutWidthözelliği de ayarlamanız gerekebilir :

button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
button.titleLabel.textAlignment = NSTextAlignmentCenter;
button.titleLabel.preferredMaxLayoutWidth = button.frame.size.width;

3

LineBreakMode öğesini NSLineBreakByWordWrapping (IB veya kod olarak) olarak ayarlamak, düğme etiketini çok satırlı yapar, ancak düğmenin çerçevesini etkilemez.

Düğmenin dinamik başlığı varsa, bir hile vardır: gizli UILabel'i aynı yazı tipiyle koyun ve yüksekliğini mizanpaj ile düğmenin yüksekliğine bağlayın; metin düğme ve etiket ve otomatik yerleşim olarak ayarlandığında tüm işi yapacak.

Not

Tek satır düğmesinin iç boyut yüksekliği etiketlerinkinden daha büyüktür, bu nedenle etiketin yüksekliğinin daralmasını önlemek için dikey İçeriği Sarma Önceliği düğmenin dikey İçerik Sıkıştırma Direnci'nden daha büyük olmalıdır.


3

In Swift 5.0 ve Xcode 10.2

//UIButton extension
extension UIButton {
     //UIButton properties
     func btnMultipleLines() {
         titleLabel?.numberOfLines = 0
         titleLabel?.lineBreakMode = .byWordWrapping
         titleLabel?.textAlignment = .center        
     }
}

Sizin de ViewController böyle çağrısı

button.btnMultipleLines()//This is your button

3

Swift 5, UIButton'daki çok satırlı metin için

  let button = UIButton()
  button.titleLabel?.lineBreakMode = .byWordWrapping
  button.titleLabel?.textAlignment = .center
  button.titleLabel?.numberOfLines = 0 // for Multi line text

2

Mükemmel çalışıyor.

Bunu Plist gibi yapılandırma dosyasıyla kullanmak için ekleyin, çok satırlı başlığı yazmak için CDATA kullanmanız gerekir, örneğin:

<string><![CDATA[Line1
Line2]]></string>

2

Otomatik düzen kullanıyorsanız.

button.titleLabel?.adjustsFontSizeToFitWidth = true
button.titleLabel?.numberOfLines = 2

2

hızlı 4.0

btn.titleLabel?.lineBreakMode = .byWordWrapping
btn.titleLabel?.textAlignment = .center
btn.setTitle( "Line1\nLine2", for: .normal)

2

Bu günlerde, arayüz oluşturucuda duruma göre erişilebilir olması için bu tür şeylere gerçekten ihtiyacınız varsa, bunu aşağıdaki gibi basit bir uzantıyla yapabilirsiniz:

extension UIButton {
    @IBInspectable var numberOfLines: Int {
        get { return titleLabel?.numberOfLines ?? 1 }
        set { titleLabel?.numberOfLines = newValue }
    }
}

Daha sonra, numberOfLines öğesini herhangi bir UIButton veya UIButton alt sınıfında etiketmiş gibi bir özellik olarak ayarlayabilirsiniz. Aynı şey, bir görünümün katmanının köşe yarıçapı veya yayınladığı gölgenin nitelikleri gibi genellikle erişilemeyen diğer tüm değerler için de geçerlidir.


0

Kendi düğme sınıfınızı döndürün. Uzun vadede açık ara en iyi çözüm. UIButton ve diğer UIKit sınıfları, bunları nasıl özelleştirebileceğiniz konusunda çok kısıtlayıcıdır.


0
self.btnError.titleLabel?.lineBreakMode = NSLineBreakMode.byWordWrapping

self.btnError.titleLabel?.textAlignment = .center

self.btnError.setTitle("Title", for: .normal)

0

Ben dahil jessecurry cevabını içinde STAButton benim parçasıdır STAControls açık kaynak kütüphanesi. Şu anda geliştirdiğim uygulamalardan birinde kullanıyorum ve ihtiyaçlarım için çalışıyor. Nasıl geliştirilebileceği veya bana çekme istekleri gönderebileceği konularla ilgili olarak çekinmeyin.


0

Başlık etiketinin boşluğunu düğmeye sabitlemek için setTitle'dan önce titleEdgeInsets ve diğer özellikleri ayarlayın:

    let set = UIButton()
    sut.titleLabel?.lineBreakMode = .byWordWrapping
    sut.titleLabel?.numberOfLines = 0
    sut.titleEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 20, right: 20)
    sut.setTitle("Dummy button with long long long long long long long long title", for: .normal)

PS: titleLabel? .TextAlignment ayarını gerekli değil ve başlık hizalandı .natural.


-4

Bir kontrole bir alt görünüm eklemek uygun olsa da, aslında işe yarayacağının garantisi yoktur, çünkü kontrolün orada olmasını beklemeyebilir ve bu nedenle kötü davranabilir. Bundan kurtulabiliyorsanız, etiketi düğmenin kardeş görünümü olarak ekleyin ve çerçevesini düğmeyle çakışacak şekilde ayarlayın; düğmenin üzerinde görünecek şekilde ayarlandığı sürece, düğmenin yapabileceği hiçbir şey onu gizleyemez.

Başka bir deyişle:

[button.superview addSubview:myLabel];
myLabel.center = button.center;

2
Lütfen, bu tür çirkin bir yaklaşım önerirseniz, en azından kod örneğinizde hata yapmayın :). Bir alt görünümse etiket, düğmeyle aynı merkeze sahip olmamalıdır. MyLabel.frame = button.bounds kullanın; veya myLabel.center = cgPointMake (button.frame.size.with * 0.5, button.frame.size.height * 0.5)
JakubKnejzlik

1
@GrizzlyNetch Özellikle tavsiye ediyorum değil düğmeye subview eklemek için. addSubview:burada onu buttondenetimine ekler , böylece düğmenin bir kardeşi yapar, böylece merkezlerini eşleştirmek doğrudur.
Brent Royal-Gordon

Ah, benim hatam! Haklısın, ben kontrolünde "küçük" gerçeği kaçırdım: D ... üzgünüm :)
JakubKnejzlik

Tam olarak sorulan soru olmadığı için, öğe düğmesinin bir başlığı olduğundan, bu çözüm soruyu uygulamanın kötü bir yolu olacaktır.
Pablo Blanco

Bu, iPhone OS 2.0'da makul bir öneriydi. Şimdiye kadar bunu yapmanın çok daha iyi yolları var. : ^)
Brent Royal-Gordon
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.