Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is this CoreText? - Aviary text pinch zoom expand

I am looking into making an app where a user can change the size and orientation of UITextField. I was looking into Aviary app and what I see is that users can not only increase or decrease the size of the text but they can also change its orientation.

enter image description here

So the questions I want to ask are

1) Are they using CoreText to do this are they using just plain old UILabel or UIText?

2) I don't know how you can dynamically resize? Are they using UIView?

3) I have googled CoreText tutorials, examples, checked apple docs and sample projects, looked into cocoa controls and github and I still don't see any sample code or tutorial that will show how this is done.

Would anyone be kind enough to point me in some direction or a tutorial?

like image 625
Sam B Avatar asked Apr 16 '13 13:04

Sam B


1 Answers

Regarding the appearance of the font, there are a couple of options:

  1. You can use the standard UILabel to achieve the most of the effects (font, size, color, rotation) you see here. The one feature that is beyond the standard UILabel is the white stroke around the font. But, effective iOS 6, you can also achieve the effect of the white stroke around the red text with a standard UILabel using its attributedText property, which is a NSAttributedString.

  2. In iOS versions prior to 6.0, to achieve the white stroke color around the text, you had to use CoreGraphics or CoreText.

Regarding the dynamic resizing, rotating, and moving of the text, they're undoubtedly just using gesture recognizers that adjust the transform property of the view (more accurately, probably adjusting transform for rotation, adjusting the center or frame for dragging, and adjusting both the frame and font size for resizing (if you just use scale transformation, you can end up with undesirable pixelation).

You'll get quite a few good hits if you search Stack Overflow for questions regarding gesture recognizers and dragging, resizing, and rotating of views.


In iOS 6, if you want the red text with a white border with a UILabel, you could do something like:

// create attributes dictionary

NSDictionary *attributes = @{
                             NSFontAttributeName            : [UIFont systemFontOfSize:48.0],
                             NSForegroundColorAttributeName : [UIColor redColor],
                             NSStrokeColorAttributeName     : [UIColor whiteColor],
                             NSStrokeWidthAttributeName     : @(-3)
                             };

// make the attributed string

NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:@"bigcat"
                                                                   attributes:attributes];

self.label.attributedText = stringToDraw;

For information about attributed strings in iOS, see:

  • WWDC 2012 - #222 - Introduction to Attributed Strings for iOS

  • WWDC 2012 - #230 - Advanced Attributed Strings for iOS


If you need to support iOS versions prior to iOS 6, you have to use CoreText or CoreGraphics. A CoreText rendition might look like:

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];

    if (!self.text)
        return;

    // create a font

    CTFontRef sysUIFont = CTFontCreateUIFontForLanguage(kCTFontSystemFontType, self.fontSize, NULL);

    // create attributes dictionary

    NSDictionary *attributes = @{
                                 (__bridge id)kCTFontAttributeName            : (__bridge id)sysUIFont,
                                 (__bridge id)kCTForegroundColorAttributeName : (__bridge id)[self.fillColor CGColor],
                                 (__bridge id)kCTStrokeColorAttributeName     : (__bridge id)[self.borderColor CGColor],
                                 (__bridge id)kCTStrokeWidthAttributeName     : @(-3)
                                 };

    // make the attributed string

    NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:self.text
                                                                       attributes:attributes];

    // begin drawing

    CGContextRef context = UIGraphicsGetCurrentContext();

    // flip the coordinate system

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    // create CTLineRef

    CTLineRef line = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)stringToDraw);

    // figure out the size (which we'll use to center it)

    CGFloat ascent;
    CGFloat descent;
    CGFloat width = CTLineGetTypographicBounds(line, &ascent, &descent, NULL);
    CGFloat height = ascent + descent;
    CGSize stringSize = CGSizeMake(width, height);

    // draw it

    CGContextSetTextPosition(context,
                             (self.bounds.size.width  - stringSize.width)  / 2.0,
                             (self.bounds.size.height - stringSize.height + descent) / 2.0);
    CTLineDraw(line, context);

    // clean up

    CFRelease(line);
    CFRelease(sysUIFont);
}

A more complete implementation of the above can be found in my GitHub CoreText Demonstration.


Here is a very simple Core Graphics implementation of drawRect that writes text with a outline around the text:

@implementation CustomView

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];

    if (!self.text)
        return;

    // begin drawing

    CGContextRef context = UIGraphicsGetCurrentContext();

    // flip the coordinate system

    CGContextSetTextMatrix(context, CGAffineTransformMakeRotation(M_PI_4 / 2.0));
    CGContextTranslateCTM(context, 0, self.bounds.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    // write the text

    CGContextSelectFont (context, "Helvetica", self.fontSize, kCGEncodingMacRoman);
    CGContextSetTextDrawingMode (context, kCGTextFillStroke);
    CGContextSetStrokeColorWithColor(context, [[UIColor whiteColor] CGColor]);
    CGContextSetLineWidth(context, 1.5);
    CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
    CGContextShowTextAtPoint (context, 40, 100, [self.text UTF8String], [self.text length]);
}

@end
like image 75
Rob Avatar answered Oct 23 '22 07:10

Rob