Question

J'ai le code suivant ...

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

... l'idée étant que je peux avoir un texte multiligne pour le bouton, mais le texte est toujours masqué par la valeur backgroundImage de l'UIButton. Un appel de journalisation pour afficher les sous-vues du bouton indique que le libellé UILabel a été ajouté, mais que le texte lui-même n’est pas visible. Est-ce un bug dans UIButton ou est-ce que je fais quelque chose de mal?

Était-ce utile?

La solution

Pour iOS 6 et les versions ultérieures, utilisez ce qui suit pour autoriser plusieurs lignes:

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

Pour iOS 5 et versions antérieures, utilisez les méthodes suivantes pour autoriser plusieurs lignes:

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

2017, pour iOS9 avant ,

En général, il suffit de faire ces deux choses:

  1. choisissez " Texte attribué "
  2. sur le " Line Break " popup, sélectionnez "Saut à la ligne"

Autres conseils

La réponse sélectionnée est correcte, mais si vous préférez procéder de la sorte dans Interface Builder, procédez comme suit:

pic

Si vous souhaitez ajouter un bouton dont le titre est centré sur plusieurs lignes, définissez les paramètres de votre Interface Builder pour le bouton:

[ici]

Pour IOS 6:

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

Comme

UILineBreakModeWordWrap and UITextAlignmentCenter

sont obsolètes dans IOS 6 et les suivantes.

Pour reprendre la suggestion de Roger Nolan, mais avec un code explicite, voici la solution générale:

button.titleLabel?.numberOfLines = 0

SWIFT 3

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

Il existe un moyen beaucoup plus simple:

someButton.lineBreakMode = UILineBreakModeWordWrap;

(Éditer pour iOS 3 et versions ultérieures:)

someButton.titleLabel.lineBreakMode = UILineBreakModeWordWrap;

Aligner à gauche sur iOS7 avec autolayout:

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

Tout d’abord, sachez que UIButton contient déjà un UILabel. Vous pouvez le définir avec –setTitle: forState: .

Le problème avec votre exemple est que vous devez définir la propriété numberOfLines de UILabel sur une valeur autre que sa valeur par défaut de 1. Vous devez également consulter la propriété lineBreakMode .

Dans Xcode 9.3, vous pouvez le faire en utilisant le storyboard comme ci-dessous,

.

 entrez la description de l'image ici

Vous devez définir le titre du bouton textAlignment au centre

button.titleLabel? .textAlignment = .center

Vous n'avez pas besoin de définir le texte du titre avec une nouvelle ligne (\ n) comme ci-dessous,

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

Définissez simplement le titre,

button.setTitle ("Bonne réponse", pour: .normal)

Voici le résultat,

 entrez la description de l'image ici

Pour ceux qui utilisent le storyboard de Xcode 4, vous pouvez cliquer sur le bouton. Dans le volet droit de la fenêtre Utilitaires, sous Inspecteur des attributs, vous verrez une option pour le saut de ligne. Choisissez Word Wrap, et vous devriez être prêt à partir.

Les réponses ci-dessous vous expliquent comment réaliser un titre de bouton multiligne par programme.

Je voulais juste ajouter que si vous utilisez des storyboards, vous pouvez taper [Ctrl + Entrée] pour forcer une nouvelle ligne sur le champ du titre d'un bouton.

HTH

Vous devez ajouter ce code:

buttonLabel.titleLabel.numberOfLines = 0;

Quant à l'idée de Brent de mettre le titre UILabel comme point de vue d'un frère, cela ne me semble pas une très bonne idée. Je continue de penser aux problèmes d'interaction avec UILabel en raison de ses événements tactiles qui ne passent pas à travers le point de vue d'UIButton.

D'un autre côté, avec UILabel comme sous-vue de UIButton, je suis assez à l'aise sachant que les événements tactiles seront toujours propagés vers la vue d'ensemble de UILabel.

J'ai adopté cette approche et n'ai remarqué aucun des problèmes signalés avec backgroundImage. J'ai ajouté ce code dans l'option -titleRectForContentRect: d'une sous-classe UIButton, mais le code peut également être placé dans la routine de dessin de la vue d'ensemble UIButton. Dans ce cas, vous devez remplacer toutes les références à self par la variable de UIButton.

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

J'ai pris le temps et écrit un peu plus à ce sujet ici . Là aussi, je pointe une solution plus courte, bien qu’elle ne convienne pas parfaitement à tous les scénarios et implique quelques piratages de vues privées. Vous pouvez également télécharger une sous-classe UIButton prête à être utilisée.

Si vous utilisez la disposition automatique sur iOS 6, vous devrez peut-être également définir la propriété preferredMaxLayoutWidth :

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

Cela fonctionne parfaitement.

Ajouter pour utiliser ceci avec un fichier de configuration comme Plist, vous devez utiliser CDATA pour écrire le titre multiligne, comme ceci:

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

La définition de lineBreakMode sur NSLineBreakByWordWrapping (dans IB ou dans le code) crée une étiquette de bouton multiligne, mais n'affecte pas le cadre du bouton.

Si le bouton a un titre dynamique, il y a un truc: mettez UILabel caché avec la même police et liez sa hauteur à la hauteur du bouton avec layout; lorsque le texte est défini sur button, sur l'étiquette et que l'autolayout effectue tout le travail.

Remarque

La taille intrinsèque du bouton d'une ligne est plus grande que celle de l'étiquette. Par conséquent, pour éviter que la hauteur de l'étiquette ne soit réduite à la verticale, la priorité d'accouplement du contenu doit être supérieure à la résistance verticale du bouton du contenu.

Si vous utilisez la mise en page automatique.

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

J'ai eu un problème avec la mise en page automatique. Après avoir activé le mode multiligne, le résultat était le suivant:
entrer la description de l'image ici
la taille titleLabel n'affecte donc pas la taille du bouton
J'ai ajouté Contraintes en fonction de contentEdgeInsets (dans ce cas, contentEdgeInsets était (10, 10, 10, 10)

après avoir appelé makeMultiLineSupport () :
entrer la description de l'image ici
espérons que cela vous aide (swift 5.0):

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

}

Ces jours-ci, si vous avez vraiment besoin que ce genre de chose soit accessible au cas par cas dans le constructeur d'interface, vous pouvez le faire avec une simple extension comme celle-ci:

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

Ensuite, vous pouvez simplement définir numberOfLines en tant qu’attribut sur n’importe quelle sous-classe UIButton ou UIButton, comme s’il s’agissait d’une étiquette. Il en va de même pour toute une série d'autres valeurs généralement inaccessibles, telles que le rayon de l'angle du calque d'une vue ou les attributs de l'ombre projetée.

Lancez votre propre classe de boutons. C'est de loin la meilleure solution à long terme. UIButton et les autres classes UIKit sont très restrictifs quant à la manière de les personnaliser.

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

self.btnError.titleLabel?.textAlignment = .center

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

rapide 4.0

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

J'ai incorporé la réponse de jessecurry dans STAButton qui fait partie de mon STAControls bibliothèque open source. Je l'utilise actuellement dans l'une des applications que je développe et cela fonctionne pour mes besoins. N'hésitez pas à ouvrir des questions sur la façon de l'améliorer ou de m'envoyer des demandes de tirage.

Dans Swift 5.0 et Xcode 10.2

SharedClass exemple écrivez une fois et utilisez tous les articles

Il s’agit de votre classe partagée (comme cela, vous utilisez toutes les propriétés des composants)

import UIKit

class SharedClass: NSObject {

     static let sharedInstance = SharedClass()

     private override init() {

     }
  }

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

Dans votre appel ViewController , comme ceci

button.btnMultipleLines()//This is your button

Bien qu'il soit correct d'ajouter une sous-vue à un contrôle, rien ne garantit qu'il fonctionnera réellement, car le contrôle pourrait ne pas s'attendre à ce qu'il soit là et pourrait donc se comporter de manière médiocre. Si vous pouvez vous en sortir, ajoutez simplement l'étiquette en tant que vue parentale du bouton et définissez son cadre de sorte qu'il chevauche le bouton; tant qu'il est configuré pour apparaître en haut du bouton, rien ne le masquera.

En d'autres termes:

[button.superview addSubview:myLabel];
myLabel.center = button.center;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top