In my iPhone app i need to implement a different type of transition.
that was
next view open from the current view,
it stats like a dot, and the dot expands slowly like a circle with in the circle next view is to be displayed partially with in the part of the circle , finally the circle expands totally the next view appears completely.
I search lots of transitions like CATransitions, and some animations on cocoa controller, but i didn't find this type of transition, can any one help me please.
Well I think I can offer you a workaround. Instead of pushing to the next view like a dot . I suggest you add a simple dot animation in the ViewWillAppear
of the view in which you have to get pushed. Now the push method would remain the same like
[self.navigationController pushViewController:NewView animated:YES];
But in the ViewWillAppear
the code would be such that the dot would expand to a circle and reveal the New View beneath it. Hope you understand the logic I am trying to explain here. Any issue do let me know .
in my case I did it that way:
set a CAShapeLayer
instance as the layer's mask property of your custom view subclass
@interface MyCustomView ()
@property (nonatomic, strong) CircleShapeLayer *circleShapeLayer;
@end
@implementation MyCustomView
- (id) initWithFrame: (CGRect) frame {
self = [super initWithFrame: CGRectZero];
if (self) {
self.layer.mask = self.shapeLayer;
[self.layer.mask setValue: @(0) forKeyPath: @"transform.scale"];
}
return self;
}
zoom this mask layer to fullsize. code of your view:
- (void) zoom {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath: @"transform.scale"];
animation.fromValue = [self.layer.mask valueForKeyPath: @"transform.scale"];
animation.toValue = @(1);
animation.duration = 2.0;
animation.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
animation.delegate = self;
// Important: change the actual layer property before installing the animation.
[self.layer.mask setValue: animation.toValue forKeyPath: animation.keyPath];
// Now install the explicit animation, overriding the implicit animation.
[self.layer.mask addAnimation: animation forKey: animation.keyPath];
return;
}
- (CAShapeLayer *) circleShapeLayer {
if (!_ circleShapeLayer) {
_circleShapeLayer = [SGMaskLayer layer];
_circleShapeLayer.delegate = _shapeLayer;
_circleShapeLayer.frame = self.bounds;
_circleShapeLayer.needsDisplayOnBoundsChange = YES;
}
return _circleShapeLayer;
}
@end
the code of the mask layer:
@interface CircleShapeLayer : CAShapeLayer
@end
@implementation CircleShapeLayer
- (void) drawLayer: (CALayer *) layer inContext: (CGContextRef) ctx {
UIGraphicsPushContext(ctx);
UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect: self.bounds];
self.path = circlePath.CGPath;
UIGraphicsPopContext();
}
@end
from the documentation:
The layer’s alpha channel determines how much of the layer’s content and background shows through. Fully or partially opaque pixels allow the underlying content to show through but fully transparent pixels block that content.
The default value of this property is nil nil. When configuring a mask, remember to set the size and position of the mask layer to ensure it is aligned properly with the layer it masks.
so I drew a circle with UIBezierPath to achieve the round mask. at the beginning I set the mask's scale factor to 0 so nothing of the view's layer is visible. then the scale factor is set to 1 (filling the layer's bounds) animated which gives a nice animation of a circle increasing it's radius from the center.
you might need one more animation shifting the center point of your view. both animations can be wrapped in a CAAnimationGroup.
Open in first view:
//Delegate method for annotation did select - (void)tapOnAnnotation:(RMAnnotation *)annotation onMap:(RMMapView *)map; { //To get the touch point of the GMS marker to set them as circle transiton pos CGPoint markerPoint = annotation.position; x = markerPoint.x; y = markerPoint.y;
circleSize = 10;
radiusChange = 0;
//Populate Same Values to next view to close
VenueScreen.x = x;
VenueScreen.y = y;
VenueScreen.view.hidden = YES;
timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(openVenueScreen) userInfo:nil repeats:YES];
VenueScreen.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:VenueScreen.view];
}
//Circular transition to open Next view
-(void)openVenueScreen
{
VenueScreen.view.hidden = NO;
VenueScreen.view.userInteractionEnabled = NO;
VenueScreen.view.alpha = 0.9;
self.view.userInteractionEnabled = NO;
int rChange = 0; // Its doing proper masking while changing this value
int radius = circleSize-rChange;
CAShapeLayer *circleShapeLayer = [CAShapeLayer layer];
// Make a circular shape
circleShapeLayer.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(x+radiusChange, y+radiusChange, 2.0*radius, 2.0*radius)
cornerRadius:radius].CGPath;
radiusChange = radiusChange-10;
// Configure the apperence of the circle
[[VenueScreen.view layer] setMask:circleShapeLayer];
//Start Transition
circleSize = circleSize+10;
if (circleSize > 480)
{
[[VenueScreen.view layer] setMask:nil];
[timer invalidate]; //Stop titmer
VenueScreen.view.userInteractionEnabled = YES;
self.view.userInteractionEnabled = YES;
VenueScreen.view.alpha = 1;
//Populate to next view to close
VenueScreen.radiusChange = radiusChange;
}
}
Close in Next View:
//Close button Action
-(IBAction)DismissVenueScreen:(id)sender;
{
timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(dismissVenueScreen) userInfo:nil repeats:YES];
NSLog(@"close button clciked");
}
//Circular trasition to Close window
-(void)dismissVenueScreen
{
int rChange = 0; // Its doing proper masking while changing this value
int radius = circleSize-rChange;
CAShapeLayer *circleShapeLayer = [CAShapeLayer layer];
// Make a circular shape
circleShapeLayer.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(x+radiusChange,y+radiusChange, 2.0*radius, 2.0*radius)
cornerRadius:radius].CGPath;
// Configure the apperence of the circle
[[self.view layer] setMask:circleShapeLayer];
self.view.layer.masksToBounds = YES;
radiusChange = radiusChange+10;
circleSize = circleSize-10;
if (circleSize <= 0)
{
[timer invalidate]; //Stop titmer
[[self.view layer] setMask:nil];
[self.view removeFromSuperview];
circleSize = 480;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With