#define DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) / 180.0 * M_PI)
CGAffineTransform cgCTM = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(45));
myImage.transform = cgCTM;
A collection of handy code snippets in the languages that I use on a daily basis.
January 30, 2009
iPhone: Rotate a UIImageView
Here's a simple little snippet that's useful if you want to rotate a UIImageView continuously for something like a clock hand graphic:
Labels:
cocoa,
iphone,
objective-c,
rotate,
uiimageview
iPhone: Custom font loading : complete example
UPDATE: It looks like someone has built a far more robust custom font engine than my example here. I haven't tried it yet, but the example project looks great: http://github.com/zynga/FontLabel
This code was cobbled together from a couple different posts I found on blogs and iphone forums, here and here. This is a complete example, which nobody wanted to supply - I hope this is useful to someone. The one major hole is that is does not support multi-line text. Let me know if you figure out a good way to handle it :)
I'm just going to post my 2 classes here. I've set up a base class that does the drawing, and a subclass that defines font-specific configuration. You'll have to put your .ttf (TrueType) font in the bundle, and use it's name there to customize your own font subclass. You'll also have to set the glyph offset in the subclass - a font-editing tool can help with this.
Here we go:
CustomFontBase.h
CustomFontBase.m
This code was cobbled together from a couple different posts I found on blogs and iphone forums, here and here. This is a complete example, which nobody wanted to supply - I hope this is useful to someone. The one major hole is that is does not support multi-line text. Let me know if you figure out a good way to handle it :)
I'm just going to post my 2 classes here. I've set up a base class that does the drawing, and a subclass that defines font-specific configuration. You'll have to put your .ttf (TrueType) font in the bundle, and use it's name there to customize your own font subclass. You'll also have to set the glyph offset in the subclass - a font-editing tool can help with this.
Here we go:
CustomFontBase.h
@interface CustomFontBase : UIView { NSMutableString *curText; UIColor *fontColor; UIColor *bgColor; int fontSize; NSString *fontName; NSString *fontExtension; float autoSizeWidth; int glyphOffset; BOOL isGlowing; UIColor *glowColor; } - (void)updateText:(NSString*)newText; - (void)initTextWithSize:(float)size color:(UIColor*)color bgColor:(UIColor*)bgColor; - (void)setGlow:(BOOL)glowing withColor:(UIColor*)color; - (void)autoSizeWidthNow; @property (nonatomic, retain) NSMutableString *curText; @end
CustomFontBase.m
#import "CustomFontBase.h" @implementation CustomFontBase @synthesize curText; - (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // set defaults [self setBackgroundColor:[UIColor clearColor]]; bgColor = [UIColor clearColor]; [self setCurText: [[NSMutableString alloc] initWithString:@""] ]; fontColor = [UIColor whiteColor]; fontSize = 15; isGlowing = FALSE; [self setContentMode:UIViewContentModeTopLeft]; // make sure it doesn't scale/deform when setFrame is called } return self; } - (void)drawRect:(CGRect)rect { // get context and flip for normal coordinates CGContextRef context = UIGraphicsGetCurrentContext(); CGContextTranslateCTM ( context, 0, self.bounds.size.height ); CGContextScaleCTM ( context, 1.0, -1.0 ); // Get the path to our custom font and create a data provider. NSString *fontPath = [[NSBundle mainBundle] pathForResource:fontName ofType:fontExtension]; CGDataProviderRef fontDataProvider = CGDataProviderCreateWithFilename([fontPath UTF8String]); // Create the font with the data provider, then release the data provider. CGFontRef customFont = CGFontCreateWithDataProvider(fontDataProvider); CGDataProviderRelease(fontDataProvider); // Set the customFont to be the font used to draw. CGContextSetFont(context, customFont); // prepare characters for printing NSString *theText = [NSString stringWithString: curText]; int length = [theText length]; unichar chars[length]; CGGlyph glyphs[length]; [theText getCharacters:chars range:NSMakeRange(0, length)]; // draw bg if( bgColor != [UIColor clearColor] ) { CGRect bgRect = CGRectMake (0, 0, self.bounds.size.width, self.bounds.size.height); CGContextSetFillColorWithColor( context, bgColor.CGColor ); CGContextFillRect( context, bgRect ); } // Set how the context draws the font, what color, how big. CGContextSetTextDrawingMode(context, kCGTextFill); CGContextSetFillColorWithColor(context, fontColor.CGColor ); CGContextSetFontSize(context, fontSize); // set a glow? if( isGlowing ) { //CGContextSetShadow(context, CGSizeMake(0,0), 3 ); CGContextSetShadowWithColor( context, CGSizeMake(0,0), 3, glowColor.CGColor ); } // Loop through the entire length of the text. for (int i = 0; i < length; ++i) { // Store each letter in a Glyph and subtract the MagicNumber to get appropriate value. glyphs[i] = [theText characterAtIndex:i] + glyphOffset; } // draw the glyphs CGContextShowGlyphsAtPoint( context, 0, 0 + fontSize * .25, glyphs, length ); // hack the y-point to make sure it's not cut off below font baseline - this creates a perfect vertical fit // get width of text for autosizing the frame later (perhaps) CGPoint textEnd = CGContextGetTextPosition( context ); autoSizeWidth = textEnd.x; // clean up the font CGFontRelease( customFont ); } // call this after creating the LandscapeText object to set the styling - (void)initTextWithSize:(float)size color:(UIColor*)color bgColor:(UIColor*)txtBgColor { // store font properties fontColor = color; fontSize = size; bgColor = txtBgColor; // autoscale height to font size [self setFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, fontSize)]; } // set new text to display - (void)updateText:(NSString*)newText { [self setCurText: [NSString stringWithString:newText] ]; [self setNeedsDisplay]; } - (void)setGlow:(BOOL)glowing withColor:(UIColor*)color { glowColor = color; isGlowing = glowing; } - (void)autoSizeWidthNow { //printf( "autoSizeWidth = %f \n", autoSizeWidth ); [self setFrame:CGRectMake(self.frame.origin.x, self.frame.origin.y, autoSizeWidth, fontSize)]; } - (void)dealloc { [curText release]; [super dealloc]; } @endCustomFontMyFont.h
#importCustomFontMyFont.m#import "CustomFontBase.h" @interface CustomFontMyFont : CustomFontBase { } @end
#import "CustomFontMyFont.h" @implementation CustomFontMyFont - (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { // Initialization code fontName = @"MyFont"; fontExtension = @"ttf"; glyphOffset = -29; // adjust this offset per font until it prints the proper characters } return self; } - (void)dealloc { [super dealloc]; } @endUsage:
CustomFontMyFont *myLabel = [[[CustomFontMyFont alloc] initWithFrame:CGRectMake(100, 100, 55, 20)] autorelease]; [myLabel initTextWithSize:11 color:[UIColor whiteColor] bgColor:[UIColor clearColor]]; [myLabel updateText:@"Custom Font"]; [self addSubview:myLabel];
Labels:
cocoa,
custom font,
iphone,
objective-c,
truetype,
ttf
January 29, 2009
iPhone: Attach an image with one line of code
I got sick of the 4 lines of code it takes to attach and garbage collect a UIImageView to your UIView, so I wrote a static function for our DisplayUtil class to clean up this process. Check it out below and feel free to use:
+ (UIImageView*)attachImageToView:(UIView*)viewObject withId:(NSString*)imgId andRect:(CGRect)rect {
UIImageView *img = [[UIImageView alloc] initWithFrame:rect];
img.image = [UIImage imageNamed:imgId];
[viewObject addSubview:img];
[img release];
return img;
}
Labels:
addsubview,
attach,
cocoa,
function,
objective-c,
static,
uiimageview,
uiview
January 27, 2009
ActionScript 3: Prevent graphics from blocking your button
In Flash 9, a non-button graphic that lays over a real button wil prevent the user from clicking the button underneath. This was never a problem in Flash before AS3 / Flash 9, but is quite a common problem to deal with. It's quite easy to get around the issue. You simply need to disable any mouse interaction with the inactive graphic. Even though you haven't told it to act as a button, the default is to capture mouse actions as a DisplayObject. Just add this code to the non-button graphic:
Fixed!
graphic.mouseChildren = false;
graphic.mouseEnabled = false;
Fixed!
Labels:
actionscript 3,
as3,
block,
button,
click,
displayobject,
graphic
January 21, 2009
iPhone: Disable screen dimming
This can be very handy if you're developing an iPhone game, where the screen shouldn't automatically dim to save battery life. Use this code when you launch your gameplay view, and set it back when you leave gameplay:
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
January 19, 2009
iPhone: send and receive events/notifications
Objective-C has a really friendly and useful event system that allows your objects to talk to each other without any knowledge of the other objects. Events are called Notifications in Objective-C, and are routed through a system-wide object called NSNotificationCenter. You don't need to import this object - it's always available to every class.
Here's the syntax for dispatching an event/notification with an ID of "EventName":
It also sends along "self", which is a reference to the dispatching object. You could replace "self" with a reference to another object that may contain more relevant data to the event being dispatched.
To respond to this event, you need to set up a listener:
Our object, "self" is now ready to receive this event. It must have a function called "listenerFunction", but this name is up to you. Note that setting "nil" as the object lets us respond to any object in the application that sends out a notification called "EventName". Alternatively, we can listen to only one object that will send this event, by replacing "nil" with a reference to the object.
Finally, you need a function that actually does something when the event/notification is received. See below:
If we don't need to do anything with the object that was sent with the event, we can ignore the first line in the function.
[UPDATE]: Thanks to CC in the comment section for correcting my example and reminding us that we want to clean up after ourselves and remove event listeners before things are properly garbage collected. Here's the syntax for removing the listener we added above (replace "nil" with the object reference if you were listening to a specific object):
Finally, here's Apple's official Notification documentation for further reading:
http://developer.apple.com/documentation/Cocoa/Conceptual/Notifications/Introduction/introNotifications.html
Here's the syntax for dispatching an event/notification with an ID of "EventName":
[[NSNotificationCenter defaultCenter] postNotificationName:"EventName" object:self];
It also sends along "self", which is a reference to the dispatching object. You could replace "self" with a reference to another object that may contain more relevant data to the event being dispatched.
To respond to this event, you need to set up a listener:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(listenerFunction:) name:@"EventName" object:nil];
Our object, "self" is now ready to receive this event. It must have a function called "listenerFunction", but this name is up to you. Note that setting "nil" as the object lets us respond to any object in the application that sends out a notification called "EventName". Alternatively, we can listen to only one object that will send this event, by replacing "nil" with a reference to the object.
Finally, you need a function that actually does something when the event/notification is received. See below:
- (void)listenerFunction:(NSNotification *)notification
{
MyDispactherObject *incomingObject = [notification object];
NSLog(@"EVENT RECEIVED");
}
If we don't need to do anything with the object that was sent with the event, we can ignore the first line in the function.
[UPDATE]: Thanks to CC in the comment section for correcting my example and reminding us that we want to clean up after ourselves and remove event listeners before things are properly garbage collected. Here's the syntax for removing the listener we added above (replace "nil" with the object reference if you were listening to a specific object):
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"EventName" object:nil];
Finally, here's Apple's official Notification documentation for further reading:
http://developer.apple.com/documentation/Cocoa/Conceptual/Notifications/Introduction/introNotifications.html
Labels:
cocoa,
event,
iphone,
notification,
nsnotification,
objective-c
January 16, 2009
ActionScript: Random number function
I saw that one of the top results for "actionscript random number" in a Google search is incorrect, so I figured it would be a good idea to post another proper one.
Here's the ActionScript 3 version:
And here's the ActionScript 2 version:
Here's the ActionScript 3 version:
function randNum( low:int, high:int ):int
{
return Math.round( Math.random() * (high - low) ) + low;
}
And here's the ActionScript 2 version:
function randNum( low:Number, high:Number ):Number
{
return Math.round( Math.random() * (high - low) ) + low;
}
Labels:
actionscript,
actionscript 2,
actionscript 3,
as2,
as3,
function,
random number
January 15, 2009
Javascript: setInterval() - call a function every X seconds
setInterval() is used when you want a function to run repeatedly on a timer. I wrote this little html page to remind me to get up and stretch every half-hour. I keep it open in my browser during the day to keep me from slouching for too long. Programming for hours on end can lead to Repetitive Strain Injuries in the hands and arms (amongst other problems), so this could help you too :)
Note the time passed into the setInterval function. It means: 1000 milliseconds x 60 seconds x 30 minutes. setInterval uses milliseconds, so this is a clear way to describe how long you want the interval to be.
<html>
<head>
<script>
setInterval ( "tellMeToGetUp()", 1000 * 60 * 30 );
function tellMeToGetUp()
{
alert('GET UP DUDE!');
}
</script>
</head>
<body>
</body>
</html>
Labels:
function,
javascript,
js,
setinterval,
timer
January 14, 2009
iPhone: Rotate a sub view to landscape layout
After trying some other hacks, I came up with this little bit of code to rotate my full-screen UIView to landscape mode, which let me lay out all the sub views in a standard coordinate system.
#define DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) / 180.0 * M_PI)
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
self.backgroundColor = [UIColor clearColor];
[self setViewToLandscape:self];
}
return self;
}
-(void)setViewToLandscape:(UIView*)viewObject {
[viewObject setCenter:CGPointMake(160, 240)];
CGAffineTransform cgCTM = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-90));
viewObject.transform = cgCTM;
viewObject.bounds = CGRectMake(0, 0, 480, 320);
}
January 13, 2009
iPhone: Create a UIButton with a custom graphic
Here's a little code snippet if you don't want to use the standard UIButton styles. You can attach an image instead:
UIButton *button = [[UIButton buttonWithType:UIButtonTypeCustom] initWithFrame:CGRectMake(0, 0, 24, 24)];
[button addTarget:self action:@selector(prevButtonClick:) forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundImage:[UIImage imageNamed:@"IntroArrowLeft.png"] forState:UIControlStateNormal];
[self addSubview:button];
January 12, 2009
iPhone: Create a UIButton and respond to the touch
Here's the basic code to create a text button and do something when it's touched:
// add the button to the view
-(void)buildButton {
UIButton *button = [[UIButton buttonWithType:UIButtonTypeRoundedRect] initWithFrame:CGRectMake(0, 0, 150, 25)];
[button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"CLICK IT" forState:UIControlStateNormal];
[button setCenter:CGPointMake( 320 / 2, 480 - 25 )];
[self addSubview:button];
}
// respond to the button click
-(void)buttonClick:(UIView*)clickedButton
{
NSLog(@"CLICK!");
}
Subscribe to:
Posts (Atom)