问题
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.
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?
回答1:
Regarding the appearance of the font, there are a couple of options:
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 standardUILabel
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 standardUILabel
using its attributedText property, which is a NSAttributedString.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
来源:https://stackoverflow.com/questions/16038304/is-this-coretext-aviary-text-pinch-zoom-expand