Frage

Ich brauche eine Methode wie CTFrameGetvisiblestringRange, die mir den Text geben kann, der in einer bestimmten Größe mit einem Zeilenunterbrechungsmodus (dh Word Wrap) geliefert wird. Zum Beispiel habe ich eine lange Textzeile. Und ich habe ein bestimmtes Rechteck, um den darin eingewickelten Text zu zeichnen, aber wo immer der Text überzogen wird, rendere ich ihn weiterhin in einem anderen Bereich, in dem er aufgehört hat. Also brauche ich eine Methode wie:

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?

Hat jemand irgendwelche Ideen?

** Bearbeitet: Bitte sehen Sie meine Lösung.

War es hilfreich?

Lösung

Ich hatte ein ähnliches Problem und benutzte die Lösung, die Mike gepostet hat.

Es stellte sich jedoch heraus, dass das trimToWord gab mir oft ein paar zu viele Wörter, als auf meine angegebene Uilabel -Größe passen konnte. Ich fand heraus, dass, wenn ich den while -Schleifen -Operator in ein> = und nicht nur ein> geändert habe, perfekt funktioniert hat.

Ich habe auch ein paar IVARs hinzugefügt (chopIndex und remainingBody) Dass ich die verbleibende Zeichenfolge bekam, damit ich sie in meinem nächsten Uilabel anzeigen konnte.

Hier ist die Lösung, die ich verwendet habe.

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

Andere Tipps

Hier ist eine Lösung. Es ist ziemlich schnell. Es 'gisst', wo man zuerst hackt und dann das Wort nach Wort zurückrollt. SizeWithFont -Anrufe sind ziemlich teuer, daher ist dieser intiale „Vermutungsstufe“ wichtig. Die Hauptmethode ist TrimToword: SizeConstraints: Withfont.

Fühlen Sie sich frei zu kommentieren, wie ich das verbessern könnte.

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

Ich denke nicht, es gibt einen Unterabschnitt für CTFrameGetVisibleStringRange, Obwohl wir mit der Verwendung der folgenden Methode dasselbe erhalten können.

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

Apple -Dokumentation

http://developer.apple.com/library/ios/#documentation/uikit/reference/nsstring_uikit_additions/reference/reference.html

Bearbeitet: Der folgende Code zeigt meinen Ansatz an

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.
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top