Question

Je besoin d'une méthode comme CTFrameGetVisibleStringRange qui peut me donner le texte qui sera rendu dans une taille donnée fournie avec un mode de saut de ligne (c.-à-wrap mot). Par exemple, je une longue ligne de texte .. et j'ai un rectangle donné pour dessiner le texte enveloppé dans, mais où le texte est trunecated, je continue le rendre dans une autre région où il a laissé. Donc je besoin d'une méthode comme:

NSString * text = "The lazy fox jumped over the creek";
[text drawAtPoint:CGPointMake(0, 0) forWidth:20 withFont:[UIFont fontWithName:@"Arial" size:10] lineBreakMode:UILineBreakModeWordWrap];
// now I do I know how much it drew before it stopped rendering?

Quelqu'un a des idées?

** RÉVISÉ:. S'il vous plaît voir ma solution

Était-ce utile?

La solution

J'ai eu un problème similaire, et je la solution Mike affichée.

Il est apparu cependant que trimToWord me donnait souvent un peu trop de mots que pourrait tenir sur ma taille UILabel spécifiée. J'ai découvert que si je changeais l'un> = et non seulement>, il a parfaitement fonctionné opérateur de boucle tout.

J'ai aussi ajouté quelques Ivars (chopIndex et remainingBody) que je l'habitude d'obtenir la chaîne restante pour que je puisse l'afficher dans mon prochain UILabel.

Voici la solution je.

-(NSString*) rewindOneWord:(NSString*) str{
    // rewind by one word
    NSRange lastspace = [str rangeOfString:@" " options:NSBackwardsSearch];
    if (lastspace.location != NSNotFound){
        int amount = [str length]-lastspace.location;
        chopIndex -= amount;
        return [str substringToIndex:lastspace.location];
    }else {
        // no spaces, lets just rewind 2 characters at a time
        chopIndex -= 2;
        return [str substringToIndex:[str length]-2];
    }
}

// returns only how much text it could render with the given stipulations   
-(NSString*) trimToWord:(NSString*)str sizeConstraints:(CGSize)availableSize withFont:(UIFont*)font{
    if(str == @"")
        return str;

    CGSize measured = [str sizeWithFont:font constrainedToSize:CGSizeMake(availableSize.width, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap];
    // 'guess' how much we will need to cut to save on processing time
    float choppedPercent = (((double)availableSize.height)/((double)measured.height));
    if(choppedPercent >= 1.0){
        //entire string can fit in availableSize
        remainingBody = @"";
        return str;
    }

    chopIndex = choppedPercent*((double)[str length]);
    str = [str substringToIndex:chopIndex];
    // rewind to the beginning of the word in case we are in the middle of one
    do{
        str = [self rewindOneWord:str];
        measured = [str sizeWithFont:font constrainedToSize:availableSize lineBreakMode:UILineBreakModeWordWrap];
    }while(measured.height>=availableSize.height);

    //increment past the last space in the chopIndex
    chopIndex++;

    //update the remaining string
    remainingBody = [remainingBody substringFromIndex:chopIndex];

    return str;
}

Autres conseils

Voici une solution. Il est assez rapide. Il « » où devine hachez d'abord, puis roule mot par mot retour. appels sizewithFont sont assez chers, donc l'étape de cette intial "conjecture est important. La principale méthode est trimToWord: sizeConstraints:. WithFont

Ne hésitez pas à commenter sur la façon dont je pourrais améliorer cette situation.

-(NSString*) rewindOneWord:(NSString*) str{
    // rewind by one word
    NSRange lastspace = [str rangeOfString:@" " options:NSBackwardsSearch];
    if (lastspace.location != NSNotFound){
        int amount = [str length]-lastspace.location;
        return [str substringToIndex:lastspace.location];
    }else {
        // no spaces, lets just rewind 2 characters at a time
        return [str substringToIndex:[str length]-2];
    }
}

// returns only how much text it could render with the given stipulations   
-(NSString*) trimToWord:(NSString*) str sizeConstraints:(CGSize) avail withFont:(UIFont*) font{
    CGSize measured = [str sizeWithFont:font constrainedToSize:CGSizeMake(avail.width, 1000000) lineBreakMode:UILineBreakModeWordWrap];
    // 'guess' how much we will need to cut to save on processing time
    float choppedPercent = (((double)avail.height)/((double)measured.height));
    if (choppedPercent >= 1.0){
        return str;
    }

    int chopIndex = choppedPercent*((double)[str length]);
    str = [str substringToIndex:chopIndex];
    // rewind to the beginning of the word in case we are in the middle of one
    str = [self rewindOneWord:str];
    measured = [str sizeWithFont:font constrainedToSize:avail lineBreakMode:UILineBreakModeWordWrap];
    while (measured.height>avail.height){
        str = [self rewindOneWord:str];
        measured = [str sizeWithFont:font constrainedToSize:avail lineBreakMode:UILineBreakModeWordWrap];
    }
    return str;
}

Je pense do'nt, il y a subsitute pour CTFrameGetVisibleStringRange, Bien que nous puissions obtenir la même chose avec l'utilisation de la méthode ci-dessous.

- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode

Documentation d'Apple

http://developer.apple .com / bibliothèque / ios / # documentation / UIKit / référence / NSString_UIKit_Additions / référence / Reference.html

RÉVISÉ: Le Code ci-dessous montrent mon approche

NSString * text = "The lazy fox jumped over the creek";

NSArray* m_Array = [text  componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@" "]];

CGSize mySize = CGSizeMake(300,180);
NSMutableString* myString = [[NSMutableString alloc] initWithString:@""];

//The below code till the end of the while statement could be put in separate function.

CGSize tempSize = CGSizeMake(0,0);
NSInteger index = 0 ;
do
{
      [myString  appendString:[m_Array objectAtIndex:index]];
      tempSize  = [myString  sizeWithFont:myfont constrainedToSize: 
      CGSizeMake(mySize.width, CGFLOAT_MAX) lineBreakMode: UILineBreakModeWordWrap];
      index++;

}while(tempSize.height < mySize.height && index <= [m_Array count])

//Remove the string items from m_Array till the (index-1) index,

[self RemoveItems:m_Array tillIndex:(index-1)];//Plz define you own

//you have the myString which could be fitted in CGSizeMake(300,180);


//Now start with remaining Array items with the same way as we have done above.
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top