Skip to content

Instantly share code, notes, and snippets.

@kazukitanaka0611
Created July 18, 2014 09:41
Show Gist options
  • Save kazukitanaka0611/a12d1633644ccb4f23fa to your computer and use it in GitHub Desktop.
Save kazukitanaka0611/a12d1633644ccb4f23fa to your computer and use it in GitHub Desktop.
static CGFloat const SideHelperView = 2.0;
static CGFloat const AnimationDuration = .5;
struct Animation {
NSTimeInterval sideDelay;
NSTimeInterval sideDumping;
NSTimeInterval sideVelocity;
NSTimeInterval centerDelay;
NSTimeInterval centerDumping;
NSTimeInterval centerVelocity;
};
@interface AnimationView()
@property (nonatomic, strong) UIView *menuView;
@property (nonatomic, strong) UIView *sideAnchorView;
@property (nonatomic, strong) UIView *centerAnchorView;
@property (nonatomic, strong) UIColor *fillColor;
@property (nonatomic, strong) CADisplayLink *displayLink;
@end
@implementation AnimationView
struct Animation animation;
- (instancetype)initWithMenuView:(UIView *)menuView animationType:(AnimationType)animationType
{
CGRect fakeRect = menuView.frame;
fakeRect.size.height += 25.0;
if (self = [super initWithFrame:fakeRect])
{
self.menuView = menuView;
self.sideAnchorView = [[UIView alloc] initWithFrame:
CGRectMake(-SideHelperView / 2.0, -SideHelperView / 2.0,
SideHelperView, SideHelperView)];
self.centerAnchorView = [[UIView alloc] initWithFrame:CGRectMake(self.frame.size.width / 2.0 - SideHelperView / 2.0,
-SideHelperView / 2.0,
SideHelperView, SideHelperView)];
self.menuView.frame = CGRectMake(0, -self.menuView.frame.size.height,
self.menuView.frame.size.width, self.menuView.frame.size.height);
self.fillColor = menuView.backgroundColor;
self.backgroundColor = [UIColor clearColor];
self.menuView.backgroundColor = [UIColor clearColor];
[self setValuesForAnimationType:animationType];
_isAnimating = NO;
_isShow = NO;
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
if (self.menuView.subviews)
{
[self addSubview:self.menuView];
[self addSubview:self.centerAnchorView];
[self addSubview:self.sideAnchorView];
}
CALayer *sideLayer = self.sideAnchorView.layer.presentationLayer;
CALayer *centerLayer = self.centerAnchorView.layer.presentationLayer;
CGPoint sideLayerCenterPoint = CGPointMake(sideLayer.frame.origin.x + sideLayer.frame.size.width / 2.0,
sideLayer.frame.origin.y + sideLayer.frame.size.height / 2.0);
CGPoint centerLayerCenterPoint = CGPointMake(centerLayer.frame.origin.x + centerLayer.frame.size.width / 2.0,
centerLayer.frame.origin.y + centerLayer.frame.size.height / 2.0);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:sideLayerCenterPoint];
[path addQuadCurveToPoint:CGPointMake(sideLayerCenterPoint.x + self.menuView.frame.size.width,
sideLayerCenterPoint.y)
controlPoint:centerLayerCenterPoint];
[path addLineToPoint:CGPointMake(self.menuView.frame.size.width, 0)];
[path addLineToPoint:CGPointMake(0, 0)];
[path closePath];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context, path.CGPath);
[self.fillColor setFill];
CGContextFillPath(context);
}
#pragma mark - public method
- (void)show
{
[self animateMenuViewTopAppear:YES];
}
- (void)hide
{
[self animateMenuViewTopAppear:NO];
}
#pragma mark - private method
- (void)setValuesForAnimationType:(AnimationType)animationType
{
switch (animationType) {
case AnimationTypeBounce: {
animation.sideDelay = .1;
animation.sideDumping = .4;
animation.sideVelocity = .9;
animation.centerDelay = 0;
animation.centerDumping = .6;
animation.centerVelocity = .6;
}
break;
case AnimationTypeSoftBounce: {
animation.sideDelay = .1;
animation.sideDumping = .6;
animation.sideVelocity = .6;
animation.centerDelay = 0;
animation.centerDumping = .6;
animation.centerVelocity = .6;
}
break;
case AnimationTypeHardBounce: {
animation.sideDelay = .1;
animation.sideDumping = .3;
animation.sideVelocity = .7;
animation.centerDelay = 0;
animation.centerDumping = .6;
animation.centerVelocity = .4;
}
break;
case AnimationTypeWave: {
animation.sideDelay = .0;
animation.sideDumping = .5;
animation.sideVelocity = .5;
animation.centerDelay = .1;
animation.centerDumping = .5;
animation.centerVelocity = .5;
}
break;
default:
break;
}
}
- (void)animateMenuViewTopAppear:(BOOL)needsToAppear
{
if (_isShow != needsToAppear && !_isAnimating)
{
_isAnimating = YES;
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick:)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[UIView animateWithDuration:AnimationDuration
delay:animation.sideDelay
usingSpringWithDamping:animation.sideDumping
initialSpringVelocity:animation.sideVelocity
options:(UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction) animations:^{
if (needsToAppear)
{
self.sideAnchorView.frame = CGRectMake(self.sideAnchorView.frame.origin.x,
self.menuView.frame.size.height - SideHelperView / 2.0, SideHelperView, SideHelperView);
self.menuView.frame = CGRectMake(self.menuView.frame.origin.x, 0,
self.menuView.frame.size.width,
self.menuView.frame.size.height);
}
else
{
self.sideAnchorView.frame = CGRectMake(self.sideAnchorView.frame.origin.x,
SideHelperView / 2.0,
SideHelperView,
SideHelperView);
}
} completion:^(BOOL finished) {
[self.displayLink invalidate];
self.displayLink = nil;
_isShow = needsToAppear;
_isAnimating = NO;
}];
[UIView animateWithDuration:AnimationDuration
delay:animation.centerDelay
usingSpringWithDamping:animation.centerDumping
initialSpringVelocity:animation.centerVelocity
options:(UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction) animations:^{
if (needsToAppear)
{
self.centerAnchorView.frame = CGRectMake(self.centerAnchorView.frame.origin.x,
self.menuView.frame.size.height - SideHelperView / 2.0, SideHelperView, SideHelperView);
}
else
{
self.centerAnchorView.frame = CGRectMake(self.centerAnchorView.frame.origin.x,
-SideHelperView / 2.0,
SideHelperView,
SideHelperView);
self.menuView.frame = CGRectMake(self.menuView.frame.origin.x,
-self.menuView.frame.size.height,
self.menuView.frame.size.width,
self.menuView.frame.size.height);
}
} completion:nil];
}
}
- (void)tick:(CADisplayLink *)displayLink
{
[self setNeedsDisplay];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment