38 votes

iOS - Comment obtenir l'effet de gaufrage pour le texte sur UILabel?

enter image description here

Puis-je savoir comment avoir l'effet de gaufrage comme le texte "Rappels" comme indiqué sur l'image?

On dirait que le texte est intégré ?

Merci

90voto

rob mayoff Points 124153

Mise à JOUR POUR iOS 7.0

Dans iOS 7.0, Apple a ajouté un nouvel attribut, NSTextEffectAttributeName, attribuée pour les chaînes de caractères. Si votre cible de déploiement est iOS 7.0 ou version ultérieure, vous pouvez définir cet attribut NSTextEffectLetterpressStyle pour dessiner un attribuées chaîne dans un relief de style.

D'ORIGINE

Je ne peux pas dire avec certitude comment Apple attire le texte en relief. Il me semble qu'ils remplissent la chaîne de glyphes avec une couleur rougeâtre, puis appliquer une ombre autour de l'intérieur des bords de la glyphes, et aussi appliquer une très légère ombre sur le haut à l'extérieur des bords de glyphes. Je l'ai essayé et voici à quoi il ressemble:

iPhone simulator screen shot

Sur le dessus est mon rendu. Ci-dessous, qui est une simple UILabel avec de l'ombre comme Chris l'a suggéré dans sa réponse. J'ai mis une capture d'écran de l'app Rappels à l'arrière-plan.

Voici mon code.

Tout d'abord, vous avez besoin d'une fonction qui crée un masque d'image de votre chaîne. Vous allez utiliser le masque pour dessiner la chaîne elle-même, et ensuite faire une ombre qui n'apparaît autour de l'intérieur des bords de la chaîne. Cette image vient d'un canal alpha et pas de canaux RVB.

- (UIImage *)maskWithString:(NSString *)string font:(UIFont *)font size:(CGSize)size
{
    CGRect rect = { CGPointZero, size };
    CGFloat scale = [UIScreen mainScreen].scale;
    CGColorSpaceRef grayscale = CGColorSpaceCreateDeviceGray();
    CGContextRef gc = CGBitmapContextCreate(NULL, size.width * scale, size.height * scale, 8, size.width * scale, grayscale, kCGImageAlphaOnly);
    CGContextScaleCTM(gc, scale, scale);
    CGColorSpaceRelease(grayscale);
    UIGraphicsPushContext(gc); {
        [[UIColor whiteColor] setFill];
        [string drawInRect:rect withFont:font];
    } UIGraphicsPopContext();

    CGImageRef cgImage = CGBitmapContextCreateImage(gc);
    CGContextRelease(gc);
    UIImage *image = [UIImage imageWithCGImage:cgImage scale:scale orientation:UIImageOrientationDownMirrored];
    CGImageRelease(cgImage);

    return image;
}

Deuxièmement, vous avez besoin d'une fonction qui inverse que masque. Vous pourrez l'utiliser pour faire CoreGraphics de dessiner une ombre le long des bords internes de la chaîne. Ce doit être une complète image RGBA. (iOS ne semble pas des niveaux de gris+alpha des images.)

- (UIImage *)invertedMaskWithMask:(UIImage *)mask
{
    CGRect rect = { CGPointZero, mask.size };
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, mask.scale); {
        [[UIColor blackColor] setFill];
        UIRectFill(rect);
        CGContextClipToMask(UIGraphicsGetCurrentContext(), rect, mask.CGImage);
        CGContextClearRect(UIGraphicsGetCurrentContext(), rect);
    }
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

Vous pouvez les utiliser dans une fonction qui tire la corde en rouge et applique une ombre à l'intérieur des bords.

-(UIImage *)imageWithInteriorShadowAndString:(NSString *)string font:(UIFont *)font textColor:(UIColor *)textColor size:(CGSize)size
{
    CGRect rect = { CGPointZero, size };
    UIImage *mask = [self maskWithString:string font:font size:rect.size];
    UIImage *invertedMask = [self invertedMaskWithMask:mask];
    UIImage *image;
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, [UIScreen mainScreen].scale); {
        CGContextRef gc = UIGraphicsGetCurrentContext();
        // Clip to the mask that only allows drawing inside the string's image.
        CGContextClipToMask(gc, rect, mask.CGImage);
        // We apply the mask twice because we're going to draw through it twice.
        // Only applying it once would make the edges too sharp.
        CGContextClipToMask(gc, rect, mask.CGImage);
        mask = nil; // done with mask; let ARC free it

        // Draw the red text.
        [textColor setFill];
        CGContextFillRect(gc, rect);

        // Draw the interior shadow.
        CGContextSetShadowWithColor(gc, CGSizeZero, 1.6, [UIColor colorWithWhite:.3 alpha:1].CGColor);
        [invertedMask drawAtPoint:CGPointZero];
        invertedMask = nil; // done with invertedMask; let ARC free it

        image = UIGraphicsGetImageFromCurrentImageContext();
    }
    UIGraphicsEndImageContext();
    return image;
}

Ensuite, vous avez besoin d'une fonction qui prend une image et renvoie une copie avec une légère hausse de l'ombre.

- (UIImage *)imageWithUpwardShadowAndImage:(UIImage *)image
{
    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale); {
        CGContextSetShadowWithColor(UIGraphicsGetCurrentContext(), CGSizeMake(0, -1), 1, [UIColor colorWithWhite:0 alpha:.15].CGColor);
        [image drawAtPoint:CGPointZero];
    }
    UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return resultImage;
}

Enfin, vous pouvez combiner ces fonctions pour créer une image en relief de votre chaîne. J'ai mis mon image finale en UIImageView de tester facilement.

- (void)viewDidLoad
{
    [super viewDidLoad];

    CGRect rect = self.imageView.bounds;
    NSString *string = @"Reminders";
    UIFont *font = [UIFont systemFontOfSize:33];
    UIImage *interiorShadowImage = [self imageWithInteriorShadowAndString:string
        font:font
        textColor:[UIColor colorWithHue:0 saturation:.9 brightness:.7 alpha:1]
        size:rect.size];
    UIImage *finalImage = [self imageWithUpwardShadowAndImage:interiorShadowImage];

    self.imageView.image = finalImage;
}

5voto

Chris Points 251

Qui semble juste comme une ombre autour du texte. Vous pouvez la définir dans l'IB dans la même zone où vous définissez la couleur du texte - choisir une couleur appropriée pour l'ombre et de définir la façon dont vous voulez que le décalage d'ombre (dans l'exemple que vous avez posté, il semble qu'ils l'ont mis de la couleur de l'ombre à la même couleur que le texte et l'offset à 0, horizontale et 1 verticale (ce qui signifie qu'un pixel vers le haut).

Dans le code, les propriétés sont définies comme suit (en supposant que vous avez déjà configuré un UILabel nommé, à juste titre, "label":

label.shadowColor = [UIColor blackColor]; // Choose your color here - in the example
                                          // posted, they probably chose a similar color
                                          // to the text color and then set the alpha
                                          // down around 0.7 or so so the shadow would be
                                          // faint.
label.shadowOffset = CGSizeMake(0,-1);    // First parameter is horizontal, second is vertical

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X