iOS: ¿cómo encontrar el tamaño de fuente correcto (en puntos) con la misma altura que un CGRect dado?

El encabezado lo explica bastante. Tengo una imagen en la que estoy dibujando texto. Quiero que el texto tenga el tamaño de acuerdo con el tamaño de la imagen y quiero encontrar una manera de obtener una altura para la fuente que sea un poco más corta que la imagen en sí.

preguntado el 02 de mayo de 12 a las 19:05

3 Respuestas

Bien, entonces para todos los que piensan que una iteración no es evitable:

NSString *string = @"The string to render";
CGRect rect = imageView.frame;

UIFont *font = [UIFont fontWithSize:12.0]; // find the height of a 12.0pt font
CGSize size = [string sizeWithFont:font];
float pointsPerPixel = 12.0 / size.height; // compute the ratio
// Alternatively:
// float pixelsPerPoint = size.height / 12.0;
float desiredFontSize = rect.size.height * pointsPerPixel;
// Alternatively:
// float desiredFontSize = rect.size.height / pixelsPerPoint;

desiredFontSize contendrá el tamaño de fuente en puntos cuya altura sea exactamente igual a la altura del rectángulo especificado. Es posible que desee multiplicarlo por, digamos, 0.8 para que la fuente sea un poco más pequeña que el tamaño real del rect para que se vea bien.

contestado el 03 de mayo de 12 a las 05:05

Esto no parece funcionar de manera confiable: comencé una pregunta separada aquí. - user524261

@ user524261 Buena pregunta, +1 por eso. - usuario529758

¿Puedo establecer el tamaño en 6.88 pt? - Jignesh Patel

De aquí

http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/CoreText_Programming/Operations/Operations.html

CGFloat GetLineHeightForFont(CTFontRef iFont)
{
    CGFloat lineHeight = 0.0;

    check(iFont != NULL);

    // Get the ascent from the font, already scaled for the font's size
    lineHeight += CTFontGetAscent(iFont);

    // Get the descent from the font, already scaled for the font's size
    lineHeight += CTFontGetDescent(iFont);

    // Get the leading from the font, already scaled for the font's size
    lineHeight += CTFontGetLeading(iFont);

    return lineHeight;
}

Para usar esto, adivine el tamaño de un punto, encuentre la altura de la línea (puede que le importe o no el interlineado). Luego usa la relación entre la respuesta y la altura que tienes para escalar el tamaño del punto. No creo que esté garantizado que la altura sea exactamente la correcta; si le importa que sea exacta, debe iterar hasta que esté lo suficientemente cerca (use el nuevo tamaño como la nueva suposición).

contestado el 02 de mayo de 12 a las 19:05

Eso no responde a su pregunta. Él está tratando de obtener el tamaño correcto para una fuente en función de una altura específica, no averiguar qué tan alta es una fuente. También hay una propiedad UIFont llamada lineHeight que es casi seguro que tiene exactamente la misma implementación. - mbm29414

¿Por qué no solo objetos UIFont y llamadas? [font lineHeight]? - mbm29414

@ mbm30075 Quería mostrar los componentes porque es posible que al interrogador no le importe liderar o descender dependiendo de lo que esté tratando de hacer. Cuando busqué en Google, esto es lo que encontré. No vi que UIFont también lo tiene, escriba una mejor respuesta :) - lou franco

Su respuesta no evita la iteración. Pase lo que pase, tienes que iterar para obtener la respuesta correcta. - mbm29414

tu no Paso 1: averigüe la proporción de píxel a fintsize utilizando una fuente de tamaño arbitrario y, por ejemplo, NSString's -sizeWithFont: método. Luego, multiplique esta proporción por el tamaño deseado para obtener el tamaño de fuente correcto. - usuario529758

Nota: Esto supone que el tamaño de fuente siempre será más pequeño que el tamaño en puntos de CGRect. Ajuste los métodos según sea necesario para corregir esa suposición.

Prueba esto. Funciona para cualquiera de los 3 métodos principales para crear una fuente. Debería explicarse por sí mismo, pero el incremento es la cantidad que desea disminuir entre cheques. Si no le importa el tamaño exacto, haga ese número más grande para una mayor velocidad. Si te importa, hazlo más pequeño para una mayor precisión.

- (UIFont *)systemFontForRectHeight:(CGFloat)height 
                          increment:(CGFloat)increment {

    UIFont *retVal = nil;
    for (float i = height; i > 0; i = i - increment) {
        retVal = [UIFont systemFontOfSize:i];
        if ([retVal lineHeight] < height) break;
    }
    return retVal;
}
- (UIFont *)boldSystemFontForRectHeight:(CGFloat)height 
                              increment:(CGFloat)increment {

    UIFont *retVal = nil;
    for (float i = height; i > 0; i = i - increment) {
        retVal = [UIFont boldSystemFontOfSize:i];
        if ([retVal lineHeight] < height) break;
    }
    return retVal;
}

- (UIFont *)fontNamed:(NSString *)name 
        forRectHeight:(CGFloat)height 
            increment:(CGFloat)increment {

    UIFont *retVal = nil;
    for (float i = height; i > 0; i = i - increment) {
        retVal = [UIFont fontWithName:name size:i];
        if ([retVal lineHeight] < height) break;
    }
    return retVal;
}

contestado el 02 de mayo de 12 a las 20:05

¿Por qué dices eso? Comienza con un valor que se sabe que está cerca del valor final deseado (la altura del rectángulo) y permite al usuario especificar la precisión deseada para afectar la velocidad. ¿Como lo harias? - mbm29414

Como lo hace la otra respuesta. Adivina un tamaño inicial, luego usa una división + multiplicación usando la proporción encontrada para calcular el tamaño dado. Esto es O(1) y da una respuesta que siempre es correcta, la tuya es innecesariamente O(n) y es probable que no dé una respuesta correcta si el tamaño de fuente deseado no es un múltiplo entero de 1 pt. - usuario529758

Viste eso increment Qué es un tipo CGFloat? Un poco te permite ir a múltiplos más pequeños que 1pt. :-) Además, solo estás asumiendo que la proporción te da una respuesta exacta, lo cual es una suposición errónea. Te acerca, pero no garantiza una coincidencia exacta. Además, ¿cómo adivinas el tamaño inicial? - mbm29414

veo que increment es un valor de coma flotante, pero no se puede incrementar en cantidades arbitrariamente pequeñas. Además, adivinar el tamaño inicial es fácil: debe proporcionar CUALQUIER número (OK, tal vez entre, digamos, 0.00001 y 100000 para mayor precisión), ya que calcular la proporción simplemente le dará la respuesta correcta de inmediato. - usuario529758

¿Por qué crees que no puedes incrementar usando valores pequeños? Además, ¡hay un MONTÓN de valores entre 0.00001 y 100000! ¿Cómo eliges? - mbm29414

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.