Last evening I thought about Mac OSX vs. iPhone user interfaces. They have “family” likeness in usability and design, but there is a huge chasm also caused by iPhone Touch Approach of UI. We are on a new age starting, i think, the age where information is obtained by touches.
On this romantic note I want to stop talking and keep making things. The first thing I thought was original Mac OSX dock
and resolutely decided to simulate its animation on iPhone.
[youtube http://www.youtube.com/watch?v=7CkxxV5ocA0&hl=ru_RU&fs=1&]
I’ve chosen popular browsers’ icons for the buttons, don’t be surprised about IE, I
am quite neutral about this stuff
There are some code snippets. Animations of activating/deactivating buttons:
#define CONST_animation_time 0.2#define CONST_enlarge_proportion 1.3
- (IBAction) activate:(UIView*)view{ CGContextRef context
= UIGraphicsGetCurrentContext(); [UIView beginAnimations:nil
context:context]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:CONST_animation_time];
[view setCenter:UpPointOfView(view)];
CABasicAnimation *scalingAnimation =
(CABasicAnimation *)[view.layer animationForKey:@"scaling"];
if (!scalingAnimation) { scalingAnimation = [CABasicAnimation
animationWithKeyPath:@"transform"]; scalingAnimation.repeatCount=1;
scalingAnimation.duration=CONST_animation_time; scalingAnimation.autoreverses=NO;
scalingAnimation.timingFunction =
[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
scalingAnimation.fromValue=[NSValue valueWithCATransform3D:CATransform3DMakeScale(1
.0, 1.0, 1.0)]; scalingAnimation.toValue=[NSValue valueWithCATransform3D:CATransform
3DMakeScale(CONST_enlarge_proportion, CONST_enlarge_proportion, 1.0)]; }
[view.layer addAnimation:scalingAnimation forKey:@"scaling"]; view.layer.transform =
CATransform3DMakeScale(CONST_enlarge_proportion, CONST_enlarge_proportion, 1.0);
[UIView commitAnimations];}
- (IBAction) deactivate:(UIView*)view{ CGContextRef context =
UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:CONST_animation_time];
[view setCenter:DownPointOfView(view)];
CABasicAnimation *scalingAnimation =
(CABasicAnimation *)[view.layer animationForKey:@"descaling"];
if (!scalingAnimation) { scalingAnimation =
[CABasicAnimation animationWithKeyPath:@"transform"];
scalingAnimation.repeatCount=1; scalingAnimation.
duration=CONST_animation_time; scalingAnimation.
autoreverses=NO; scalingAnimation.timingFunction =
[CAMediaTimingFunction functionWithName:
kCAMediaTimingFunctionEaseOut]; scalingAnimation.
fromValue=[NSValue valueWithCATransform3D:
CATransform3DMakeScale(CONST_enlarge_proportion,
CONST_enlarge_proportion, 1.0)];
scalingAnimation.toValue=[NSValue valueWithCATransform3D
:CATransform3DMakeScale(1.0, 1.0, 1.0)]; }
[view.layer addAnimation:scalingAnimation forKey:@"descaling"];
view.layer.transform =
CATransform3DMakeScale(1.0, 1.0, 1.0); [UIView commitAnimations];}
- (BOOL) isMultipleTouchEnabled {return NO;}
UIView *activeView = nil;
- (BOOL) animateView
UIView*)view atPoint:(CGPoint)point{ BOOL isviewActive =
([view isEqual:activeView]);
if (Distance(view.center, point) <= 30)
{ if (!isviewActive) { [self activate:view];
activeView = view; return YES; }
} else if (isviewActive) { [self deactivate:view];
activeView = nil; return YES; }
return NO;}
Don’t forget to add “QuartzCore.framework” to the project.
Simple algorithm decides which buttons to active.
When finger is down algorithm finds the nearest button and activates it.
A button is deactivated when another button is closer or down finger is far than 50 points:
- (UIView*) nearestViewToPoint:(CGPoint)point{ UIView *candidateView =
nil; CGFloat candidateDistance = 100000;
for (UIView *v in [self subviews]) { CGFloat dist = Distance(v.center, point);
if (dist < candidateDistance) { candidateView = v; candidateDistance = dist; } }
return candidateView;}
- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event{ CGPoint pt =
[[touches anyObject] locationInView:self];
UIView *nearestView = [self neares
tViewToPoint:pt]; if
(![activeView isEqual:nearestView])
{ [self deactivate:activeView]; activeView = nil;
if (Distance(nearestView.center, pt)
<= 30) { [self activate:nearestView];
activeView = nearestView; } }
else if (Distance(activeView.center, pt) > 50) {
[self deactivate:activeView]; activeView = nil; }
[self setNeedsDisplay];}
-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event{ if (activeView) {
[self deactivate:activeView]; activeView = nil; }}
- (void) touchesBegan:(NSSet *)
touches withEvent:(UIEvent *) event{ if (!activeView)
[self touchesMoved:touches withEvent:event]; }
Obviously it’s hard to apply to real project, but quite interesting as a training on animations for iPhone SDK.
Look sources here or git directly.