Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 35 additions & 10 deletions MGTileMenu/MGTileMenuController.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#define MG_TILES_PER_PAGE 5 // not including paging tile (or Close button)
#define MG_DISABLED_TILE_OPACITY 0.65 // from 0.0 (fully transparent/hidden) to 1.0 (fully opaque/visible)
// Timing.
#define MG_ANIMATION_DURATION 0.15 // seconds
#define MG_ANIMATION_DURATION 0.2 // seconds
#define MG_ACTIVATION_DISMISS_DELAY 0.25 // seconds; delay between activating a tile and auto-dismissing the menu (if appropriate)


Expand Down Expand Up @@ -384,6 +384,22 @@ - (UIBezierPath *)_bezelPath
}


- (CGPoint)_centreForExtendedTileWithCentre:(CGPoint)tileCentre
{
// Used to calculate the extreme point of the tile centre when animating in and out. Extend the line going from our view centre to the given centre by a certain factor.

static float const kTileExtensionFactor = 1.2; // 20 pct

CGPoint menuCentre = MGCenterPoint([self frameForCenteredTile]);
CGPoint extendedCentre;

extendedCentre.x = menuCentre.x + (tileCentre.x - menuCentre.x) * kTileExtensionFactor;
extendedCentre.y = menuCentre.y + (tileCentre.y - menuCentre.y) * kTileExtensionFactor;

return extendedCentre;
}


// Returns the appropriate frame (within bezel view) for a tile at the given zero-based index.
// There are:
// three tiles (0-2) on the top row
Expand Down Expand Up @@ -871,6 +887,16 @@ - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished
}
[layer removeAnimationForKey:path];
}

else if ([animation isKindOfClass:[CAKeyframeAnimation class]]) {
path = [(CAKeyframeAnimation *)animation keyPath];
if (cleanUp) {
fromValue = [[(CAKeyframeAnimation *)animation values] objectAtIndex:0];
} else {
[layer setValue:[[(CAKeyframeAnimation *)animation values] lastObject] forKeyPath:path];
}
[layer removeAnimationForKey:path];
}
}

if (cleanUp) {
Expand Down Expand Up @@ -908,13 +934,13 @@ - (void)animateTilesForCurrentPage
{
// Determine which animation (to or from centre) to perform.
CGPoint centrePoint = MGCenterPoint([self frameForCenteredTile]);
CGPoint tileCentre;
CABasicAnimation *tileAnimation;
CGPoint tileCentre, extendedCentre;
CAKeyframeAnimation *tileAnimation;
UIButton *tile;
CFTimeInterval baseTime = CACurrentMediaTime();
CFTimeInterval delay = (_appeared) ? 0 : MG_ANIMATION_DURATION; // allow for menu appearance animation
CFTimeInterval duration = (_tilesArranged) ? MG_ANIMATION_DURATION - 0.05 : MG_ANIMATION_DURATION; // go to centre quicker than going back out
CFTimeInterval offset = (_tilesArranged) ? 0.05 : 0.1; // go to centre quicker than going back out
CFTimeInterval duration = 2.0 * (_tilesArranged) ? MG_ANIMATION_DURATION - 0.05 : MG_ANIMATION_DURATION; // go to centre quicker than going back out
CFTimeInterval offset = (_tilesArranged) ? 0.025 : 0.05; // go to centre quicker than going back out


// Use delegate methods to configure tiles, showing/hiding as required, if we're at the centre.
Expand Down Expand Up @@ -1013,26 +1039,25 @@ - (void)animateTilesForCurrentPage
break;
}
tile = [_tileButtons objectAtIndex:j];
tileAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
tileAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
tileAnimation.beginTime = baseTime + delay + ((CGFloat)i * offset);
[tileAnimation setValue:MG_ANIMATION_TILES forKey:@"name"];
[tileAnimation setRemovedOnCompletion:NO];
[tileAnimation setDuration:duration];
[tileAnimation setFillMode:kCAFillModeForwards];
[tileAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
tileCentre = MGCenterPoint([self frameForTileAtIndex:j]);
extendedCentre = [self _centreForExtendedTileWithCentre:tileCentre]; // the extreme centre point of the tile animation

CALayer *presentationLayer = (CALayer *)[tile.layer presentationLayer];
CGPoint currentPosition = presentationLayer.position;

if (!_tilesArranged) {
// We're going from the centre out towards the final position.
tileAnimation.fromValue = [NSValue valueWithCGPoint:(_tileAnimationInterrupted) ? currentPosition : centrePoint];
tileAnimation.toValue = [NSValue valueWithCGPoint:tileCentre];
tileAnimation.values = [NSArray arrayWithObjects:[NSValue valueWithCGPoint:(_tileAnimationInterrupted) ? currentPosition : centrePoint], [NSValue valueWithCGPoint:extendedCentre], [NSValue valueWithCGPoint:tileCentre], nil];
} else {
// We're going from the initial position in towards the centre.
tileAnimation.fromValue = [NSValue valueWithCGPoint:(_tileAnimationInterrupted) ? currentPosition : tileCentre];
tileAnimation.toValue = [NSValue valueWithCGPoint:centrePoint];
tileAnimation.values = [NSArray arrayWithObjects:[NSValue valueWithCGPoint:(_tileAnimationInterrupted) ? currentPosition : tileCentre], [NSValue valueWithCGPoint:extendedCentre], [NSValue valueWithCGPoint:centrePoint], nil];
}
[tileAnimation setDelegate:self];
[tileAnimation setValue:tile.layer forKey:MG_ANIMATION_TILE_LAYER];
Expand Down