2012-06-25 10 views
7

Estoy trabajando en una aplicación de libros para niños y me gustaría llenar dinámicamente las burbujas de discurso para los diálogos de caracteres como se muestra en las capturas de pantalla adjuntas. Las capturas de pantalla son de la aplicación Cinderella, que se desarrolló utilizando Cocos2D (o 3D), supongo. Sin embargo, me gustaría lograr esta funcionalidad usando Object-C y iOS SDK.Speech Bubble en iOS SDK usando Objective-C

Un enfoque sería:

calcular el tamaño del texto dado una fuente y el tamaño (utilizando el método NSString sizeWithFont: constrainedToSize :), a continuación, dibuje un rectángulo redondeado (usando CALayer) para encerrar ese tamaño.

Para dibujar un rectángulo redondeado, configure un CALayer con un color de fondo, un ancho de borde y un color de borde y un radio de color, y agréguelo a un objeto UIView. Eso daría un efecto de burbuja de discurso muy fácilmente.

Ahora, ¿cómo conseguiría un rincón que apuntara a la boca del personaje? ¿Cómo puedo abrir y sacar el CALayer de la boca del personaje, cómo implementaría esta animación? Mi escena principal (ilustración) sería una vista UIImage y esta ventana emergente de diálogo debería aparecer de la boca del personaje de una manera animada y después de unos segundos debería desaparecer como si volviera a la boca del personaje. Sus sugerencias serían muy apreciadas.

Si conoce algún código/artículo de muestra en algún lugar, por favor diríjalo según corresponda.

Aquí hay un enlace de vídeo de la aplicación que muestra cómo los diálogos de carácter emergente y salir cuando la burbuja del discurso: http://www.youtube.com/watch?v=umfNJLyrrNg

enter image description here

Respuesta

7

Otra forma de hacerlo es mediante el uso de imágenes con inserciones de mayúsculas. Echar un vistazo al método UIImage:

resizableImageWithCapInsets:

Básicamente se puede crear una imagen de una burbuja de tamaño mínimo, y tienen que estirarse indefinidamente, manteniendo la apariencia de las fronteras 'burbuja'.

El código siguiente especifica una imagen donde 12 píxeles en la parte superior, izquierda, inferior y derecha se conservan cuando el estiramiento/el cambio de tamaño de la imagen:

UIImage *bubble = [[UIImage imageNamed:@"bubble.png"] 
          resizableImageWithCapInsets:UIEdgeInsetsMake(12, 12, 12, 12)]; 
UIImageView *imgView = [[[UIImageView alloc] initWithImage:bubble] autorelease]; 
imgView.frame = CGRectZero; 

Animación del cambio de tamaño de un UIImageView viene gratis:

[UIView animateWithDuration:0.3 
       animations:^(void) { 
        imgView.frame = CGRectMake(50, 50, 200, 100); 
       } completion:^(BOOL finished) { 

       }]; 
+0

Veo esto mucho últimamente. Is -stretchableImageWithLeftCapWidth: topCapHeight: ¿obsoleto? –

+1

Sí, está en desuso. – hundreth

+0

Gracias. ¿Cómo sería la esquina de la burbuja del discurso que apuntaba a la boca del personaje usando resizableImageWithCapInsets :? ¿Y cómo animaría la apertura y el cierre de la burbuja del discurso? – Alex

3

El three20 framework (en realidad, Three20Style) tiene una clase de ventana en forma de llamada TTSpeechBubbleShape, que es básicamente lo que estás buscando.

Ahora, usted tiene dos opciones, tal como lo veo:

  1. o bien utilizar Three20; o

  2. analice la clase TTSpeechBubbleShape para ver cómo se implementa esto y haga lo mismo en su aplicación.

+0

Gracias. Espero que no haya ningún problema con la aceptación de mi aplicación por Apple si implemento el uso de TTSpeechBubbleShape? ¿Cómo animaría la apertura y el cierre de la burbuja del discurso? – Alex

+0

Creo que no tendrá problemas con la aprobación; una aplicación mía que usa el bocadillo de diálogo fue aprobada hace algún tiempo ... intente animar el tamaño del cuadro, lo hará. – sergio

+0

@sergio Oye, estoy intentando implementar esto, pero la clase SpeechBubble se deriva de TTShape que se deriva de NSObject. ¿Cómo puedo convertir este NSObject en una vista? – GangstaGraham

15

aquí es mi aplicación mediante la modificación de este tutorial de manzana:

https://developer.apple.com/library/ios/samplecode/quartzdemo/Listings/QuartzDemo_QuartzCurves_m.html

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef context=UIGraphicsGetCurrentContext(); 
    CGContextSetLineWidth(context, .5f); 
    CGContextSetStrokeColorWithColor(context, [UIColor lightGrayColor].CGColor); 
    CGContextSetRGBFillColor(context, 1, 1, 1, 1); 

    rect.origin.y++; 
    CGFloat radius = cornerRadius; 

    CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect); 
    CGFloat miny = CGRectGetMinY(rect), midy = CGRectGetMidY(rect), maxy = CGRectGetMaxY(rect); 

    CGMutablePathRef outlinePath = CGPathCreateMutable(); 

    if (![User isCurrentUser:message.user]) 
    { 
     minx += 5; 

     CGPathMoveToPoint(outlinePath, nil, midx, miny); 
     CGPathAddArcToPoint(outlinePath, nil, maxx, miny, maxx, midy, radius); 
     CGPathAddArcToPoint(outlinePath, nil, maxx, maxy, midx, maxy, radius); 
     CGPathAddArcToPoint(outlinePath, nil, minx, maxy, minx, midy, radius); 
     CGPathAddLineToPoint(outlinePath, nil, minx, miny + 20); 
     CGPathAddLineToPoint(outlinePath, nil, minx - 5, miny + 15); 
     CGPathAddLineToPoint(outlinePath, nil, minx, miny + 10); 
     CGPathAddArcToPoint(outlinePath, nil, minx, miny, midx, miny, radius); 
     CGPathCloseSubpath(outlinePath); 

     CGContextSetShadowWithColor(context, CGSizeMake(0,1), 1, [UIColor lightGrayColor].CGColor); 
     CGContextAddPath(context, outlinePath); 
     CGContextFillPath(context); 

     CGContextAddPath(context, outlinePath); 
     CGContextClip(context); 
     CGPoint start = CGPointMake(rect.origin.x, rect.origin.y); 
     CGPoint end = CGPointMake(rect.origin.x, rect.size.height); 
     CGContextDrawLinearGradient(context, [self normalGradient], start, end, 0); 
    } 
    else 
    { 
     maxx-=5; 
     CGPathMoveToPoint(outlinePath, nil, midx, miny); 
     CGPathAddArcToPoint(outlinePath, nil, minx, miny, minx, midy, radius); 
     CGPathAddArcToPoint(outlinePath, nil, minx, maxy, midx, maxy, radius); 
     CGPathAddArcToPoint(outlinePath, nil, maxx, maxy, maxx, midy, radius); 
     CGPathAddLineToPoint(outlinePath, nil, maxx, miny + 20); 
     CGPathAddLineToPoint(outlinePath, nil, maxx + 5, miny + 15); 
     CGPathAddLineToPoint(outlinePath, nil, maxx, miny + 10); 
     CGPathAddArcToPoint(outlinePath, nil, maxx, miny, midx, miny, radius); 
     CGPathCloseSubpath(outlinePath); 

     CGContextSetShadowWithColor(context, CGSizeMake(0,1), 1, [UIColor lightGrayColor].CGColor); 
     CGContextAddPath(context, outlinePath); 
     CGContextFillPath(context); 

     CGContextAddPath(context, outlinePath); 
     CGContextClip(context); 
     CGPoint start = CGPointMake(rect.origin.x, rect.origin.y); 
     CGPoint end = CGPointMake(rect.origin.x, rect.size.height); 
     CGContextDrawLinearGradient(context, [self greenGradient], start, end, 0); 
    } 


    CGContextDrawPath(context, kCGPathFillStroke); 

} 

- (CGGradientRef)normalGradient 
{ 

    NSMutableArray *normalGradientLocations = [NSMutableArray arrayWithObjects: 
               [NSNumber numberWithFloat:0.0f], 
               [NSNumber numberWithFloat:1.0f], 
               nil]; 


    NSMutableArray *colors = [NSMutableArray arrayWithCapacity:2]; 

    UIColor *color = [UIColor whiteColor]; 
    [colors addObject:(id)[color CGColor]]; 
    color = [StyleView lightColorFromColor:[UIColor cloudsColor]]; 
    [colors addObject:(id)[color CGColor]]; 
    NSMutableArray *normalGradientColors = colors; 

    int locCount = [normalGradientLocations count]; 
    CGFloat locations[locCount]; 
    for (int i = 0; i < [normalGradientLocations count]; i++) 
    { 
     NSNumber *location = [normalGradientLocations objectAtIndex:i]; 
     locations[i] = [location floatValue]; 
    } 
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); 

    CGGradientRef normalGradient = CGGradientCreateWithColors(space, (__bridge CFArrayRef)normalGradientColors, locations); 
    CGColorSpaceRelease(space); 

    return normalGradient; 
} 

lo que se traduce en este ... enter image description here

+1

Esto se ve bien, pero puede agregar un comentario sobre el uso. Es decir, ¿cómo se obtiene al querer poner algo de texto en la burbuja, a tenerlo realmente en la burbuja – user2011985

+1

@ user2011985, se crearía una subclase a UILabel o UITextField y se agregaría el método drawRect. Estoy modificando el código un poco para que sea más aparente. – Misha

+0

¿puede proporcionar una demostración rápida? @Misha –