Domanda

Ho bisogno di un metodo come CTFrameGetVisibleStringRange che può darmi il testo che verrà reso in una determinata dimensione fornita con una modalità di interruzione della linea (cioè avvolgimento delle parole). Ad esempio, ho una lunga fila di testo .. e ho un dato rettangolo per attirare il testo avvolto in esso, ma ovunque il testo venga trunicato, continuo a renderlo in un'altra area da dove era stato interrotto. Quindi ho bisogno di un metodo come:

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?

Qualcuno ha qualche idea?

** modificato: consulta la mia soluzione.

È stato utile?

Soluzione

Ho avuto un problema simile e ho usato la soluzione che Mike ha pubblicato.

Si è scoperto, tuttavia, quello trimToWord Spesso mi stava dando poche parole di quanto potesse adattarmi alla mia dimensione Uilabel specificata. Ho scoperto che se ho cambiato l'operatore del loop while in a> = e non solo un>, ha funzionato perfettamente.

Ho anche aggiunto alcuni Ivars (chopIndex e remainingBody) che ero solito ottenere la stringa rimanente in modo da poterla visualizzare nel mio prossimo Uilabel.

Ecco la soluzione che ho usato.

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

Altri suggerimenti

Ecco una soluzione. È abbastanza veloce. "Indovina" dove tagliare prima e poi rotola indietro per parola. Le chiamate di sizewithfont sono abbastanza costose, quindi questo passo in tutto il "indovina" è importante. Il metodo principale è TrimtoWord: SizeCostraints: Withfont.

Sentiti libero di commentare come potrei migliorare questo.

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

Non credo, c'è un sovvenzione per CTFrameGetVisibleStringRange, Sebbene possiamo ottenere lo stesso con l'uso del metodo seguente.

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

Documentazione di Apple

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

Modificato: il codice seguente mostra il mio approccio

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.
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top