Titre du Label UIButton Word Wrap with Tail Truncation

j'ai besoin d'activer l'enroulement des mots et la troncature de la queue, en même temps, sur un UIButtontitleLabel. Définir numberOfLines à quelque chose de plus que 0 ne fonctionne pas, le texte reste sur une ligne.

j'ai déjà cherché et n'ai pas trouvé de solution. Une idée?

18
demandé sur pt2ph8 2011-09-11 16:52:45

7 réponses

C'est correct:

lblTemp.lineBreakMode = NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail
lblTemp.numberOfLines = 0;

NSLineBreakMode est défini dans NSParagraphStyle.h:

typedef NS_ENUM(NSInteger, NSLineBreakMode) {       /* What to do with long lines */
    NSLineBreakByWordWrapping = 0,      /* Wrap at word boundaries, default */
    NSLineBreakByCharWrapping,      /* Wrap at character boundaries */
    NSLineBreakByClipping,      /* Simply clip */
    NSLineBreakByTruncatingHead,    /* Truncate at head of line: "...wxyz" */
    NSLineBreakByTruncatingTail,    /* Truncate at tail of line: "abcd..." */
    NSLineBreakByTruncatingMiddle   /* Truncate middle of line:  "ab...yz" */
} NS_ENUM_AVAILABLE_IOS(6_0);

notez qu'il s'agit d'un NS_ENUM, pas D'une NS_OPTION, donc il n'est pas destiné à être utilisé comme masque. Pour plus d'informations, voir .

en réalité en utilisant le / l'opérateur sur ces constantes conduit à un masque correspondant à NSLineBreakByTruncatingTail:

(NSLineBreakByWordWrapping | NSLineBreakByTruncatingTail) == 4
NSLineBreakByTruncatingTail == 4

pour autant que je sache, tronquer le dernière ligne dans la Base de Texte et aussi faire des retour à la ligne ne peut pas être fait avec le simple CTFramesetterCreateWithAttributedstring & CTFrameDraw APIs, mais peut être fait avec la mise en page ligne par ligne, ce Qu'UILabel doit faire.

iOS 6 simplifie cela en exposant de nouveaux API de dessin dans NSStringDrawing.h:

typedef NS_ENUM(NSInteger, NSStringDrawingOptions) {
    NSStringDrawingTruncatesLastVisibleLine = 1 << 5, // Truncates and adds the ellipsis character to the last visible line if the text doesn't fit into the bounds specified. Ignored if NSStringDrawingUsesLineFragmentOrigin is not also set.
    NSStringDrawingUsesLineFragmentOrigin = 1 << 0, // The specified origin is the line fragment origin, not the base line origin
    NSStringDrawingUsesFontLeading = 1 << 1, // Uses the font leading for calculating line heights
    NSStringDrawingUsesDeviceMetrics = 1 << 3, // Uses image glyph bounds instead of typographic bounds
} NS_ENUM_AVAILABLE_IOS(6_0);

@interface NSAttributedString (NSExtendedStringDrawing)
- (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);
@end

donc si vous utilisez UILabel, vous voulez que votre Nsattributedstring's NSParagraphStyle ou le lineBreakMode sur l'étiquette elle-même soit défini à :

NSLineBreakByTruncatingTail

et la propriété numberOfLines sur l'étiquette être mis à 0.

à partir des en-têtes UILabel sur nombre de lignes:

// if the height of the text reaches the # of lines or the height of the view is less than the # of lines allowed, the text will be
// truncated using the line break mode.

à Partir de la UILabel de la documentation:

This property controls the maximum number of lines to use in order to fit the label’s text into its bounding rectangle. The default value for this property is 1. To remove any maximum limit, and use as many lines as needed, set the value of this property to 0.
If you constrain your text using this property, any text that does not fit within the maximum number of lines and inside the bounding rectangle of the label is truncated using the appropriate line break mode.

le seul problème qui se pose avec cette caractéristique quelque peu obscure de UILabel est que vous ne pouvez pas obtenir la taille avant le dessin (ce qui est une nécessité pour certains uitablview + uitablviewcell dynamiques layouts) sans recourir à la modification de la NSAttributedString de NSParagraphStyle à la volée.

Comme de l'iOS 6.1.4, appel boundingRectWithSize:options:contexte, avec une NSAttributedString qui a un NSLineBreakByTruncatingTail saut de ligne mode (pour UILabel), renvoie une hauteur de ligne simple incorrecte même si les options suivantes sont transmises:

(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine)

(veuillez noter que NSStringDrawingUsesLineFragmentOrigin est une nécessité pour les chaînes multi-lignes.)

Ce qui est pire, c'est que Uilabel's lineBreakMode does Outrepasser le style de paragraphe NSAttributedStrings, vous devez donc modifier le style de paragraphe de votre chaîne attribuée pour votre calcul de taille, et plus tard pour le passer à L'UILabel afin qu'il puisse le dessiner.

C'est-à-dire, NSLineBreakByWordWrapping for-boundingRectWithSize:options:context et NSLineBreakByTruncatingTail pour L'UILabel (donc il peut, utiliser NSStringDrawingTruncatesLastVisibleline en interne, ou quoi que ce soit qu'il fait pour clip le dernière ligne)

la seule alternative si vous ne voulez pas muter le style de paragraphe de votre chaîne plus d'une fois serait de faire une simple sous-classe D'uivi qui l'emporte sur-drawRect: (avec le mode contentMode approprié réglé pour redessiner aussi), et utilise la nouvelle API de dessin d'iOS 6:

- (void)drawWithRect:(CGRect)rect options:(NSStringDrawingOptions)options context:(NSStringDrawingContext *)context NS_AVAILABLE_IOS(6_0);

Se souvenir d'utiliser NSLineBreakByWordWrapping and passing in (NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleline) comme le option.

enfin, avant iOS 6, Si vous voulez faire word wrapping + tail truncation pour une chaîne attribuée, vous devez faire line by line layout vous-même avec du texte de base.

41
répondu Marc Etcheverry 2013-05-31 01:09:19

Je l'ai résolu le même jour j'ai posté cette question en mettant un UIButton sur un UILabelnumberOfLines 3. J'avais laissé ceci inacceptable pour voir si quelqu'un avait une meilleure idée, mais apparemment il n'y a pas d'autre solution.

4
répondu pt2ph8 2011-10-11 16:57:34
[self.costomButton.titleLabel setTextAlignment:UITextAlignmentLeft];
[self.costomButton.titleLabel setNumberOfLines:3];

assurez-vous de mettre Alignment première ps: cela ne fonctionne que lorsque la version système est plus grande que 5.0

4
répondu akin 2012-06-14 09:35:09

essayez de régler le nombre de lignes de plus de 2, et réglez la hauteur en conséquence.

    m_button = [UIButton buttonWithType:UIButtonTypeCustom];
[m_button setFrame:CGRectMake(isLandscape?20:10, 40, isLandscape?300:250, 40)];
m_button.titleLabel.font  = [UIFont fontWithName:@"HelveticaNeue" size:17];
[m_btnDiscoverPoint setTitle:@"Title" forState:UIControlStateNormal];
CGRect buttonFrame = [m_button frame];

if ([m_button.titleLabel.text length]>0) {
    CGSize suggestedSize = [m_button.titleLabel.text sizeWithFont:[UIFont fontWithName:@"HelveticaNeue" size:17] constrainedToSize:CGSizeMake(FLT_MAX,m_button.frame.size.height) lineBreakMode:UILineBreakModeWordWrap];

    if (suggestedSize.width >= self.view.frame.size.width) {
        suggestedSize.width = self.view.frame.size.width-10;
        suggestedSize.height=suggestedSize.height+20;
        m_button.titleLabel.numberOfLines=2;
    }
    else{
        m_button.titleLabel.numberOfLines=1;
    }

    buttonFrame.size.width = suggestedSize.width;

    [m_button setFrame:buttonFrame];
}
[m_button setBackgroundColor:[UIColor clearColor]];
[m_button addTarget:self action:@selector(btnClickAction) forControlEvents:UIControlEventTouchUpInside];
0
répondu Meet 2012-06-08 06:58:52
button.titleLabel.numberOfLines = 2;
button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
UIFont * theFont = [UIFont systemFontOfSize: 14]; // you set
CGSize textSize = [titleStr sizeWithAttributes:@{NSFontAttributeName: theFont}];
CGFloat theWidth = kScreenWidth-otherWidthYouSet;// I thought the button's frame is content driving ,and is limited 
CGFloat ratio = theWidth*heightYouSet/((textSize.width+4)*(textSize.height+6));// 4 , 6 , is made by experience . I think the textSize is taken one line text default by the system 
NSUInteger validNum = ratio * titleStr.length;

if(ratio<1){
    [button setTitle: [[titleStr substringToIndex: validNum] stringByAppendingString: @"..."] state: yourState];

}
else{
    [button setTitle: titleStr state: yourState];
}
0
répondu dengApro 2017-11-30 05:15:10

Vous pouvez spécifier plus d'un lineBreakMode sur une étiquette en utilisant l'opérateur or.

par exemple, le code suivant envelopperait le texte de l'étiquette, et ajouterait l'ellipse sur l'extrémité de la queue du texte quand il s'étendrait au-delà de la taille de la hauteur du cadre de l'étiquette.

lblTemp.lineBreakMode = UILineBreakModeWordWrap | UILineBreakModeTailTruncation;
lblTemp.numberOfLines = 0;

mise à jour: ceci n'est pas correct. Il semble fonctionner car UILineBreakModeWordWrap 0 dans l'enum. Voir les commentaires ci-dessous.

-1
répondu charlesk 2013-08-28 18:33:41

toutes les propriétés de L'assurance-chômage sont dépréciées dans iOS utilisez les abréviations NS au lieu de L'assurance-chômage. Comme le montre l'exemple ici - NSLineBreakByTruncatingMiddle

-1
répondu aZtraL-EnForceR 2016-09-13 12:22:27