I am a bit new to iOS development. I am working on an app that has about 5,000 visual data points, organized in categories. I want to present them in a UICollectionView with very tiny UICollectionViewCells. When a user taps on something in a category, the category zooms in with the selected cell in focus. Pretty much like how the "Photos" tab of the iOS 7 Photos app works: Years > Collections > Moments.
How do I go about implementing a custom transition like that? Are there any open-source libraries already written for accomplishing this?
If you can't find any library, try to play with this code I wrote for custom animations. You can specify a start point, an end point, start scale and end scale of a view that you want to zoom and scale in or out. See below an example how I use it. The point is to use a fake view to push it with animation, then push and pop your real view without animation. viewobj is set to fade in from alpha 0 to alpha 1, zoomableView will scale from the point/scale you give as parameter to the final position you set it in your storyboard/xib. Hope it will help.
# you can create a category vor UIView and add these methods
- (void) addSubView:(UIView*)viewObj animateFromPoint:(CGPoint)point zoomableView:(UIView*)view minScale:(CGSize)scale completion:(void (^)(void))completionBlock{
CGPoint center = view.center;
[view setTransform:CGAffineTransformMakeScale(scale.width, scale.height)];
viewObj.alpha = 0;
view.center = point;
[self addSubview:viewObj];
[self addSubview:view];
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
view.center = center;
[view setTransform:CGAffineTransformMakeScale(1.0, 1.0)];
viewObj.alpha = 1;
}
completion:^(BOOL fin){
if(completionBlock)
completionBlock();
}];
}
- (void) removeFromSuperviewAnimateToPoint:(CGPoint)point zoomableView:(UIView*)view minScale:(CGSize)scale completion:(void (^)(void))completionBlock{
CGRect startFrame = view.frame;
self.alpha = 1;
[self.superview addSubview:view];
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
view.center = point;
[view setTransform:CGAffineTransformMakeScale(scale.width, scale.height)];
self.alpha = 0;
}
completion:^(BOOL fin){
[self removeFromSuperview];
[view removeFromSuperview];
[view setTransform:CGAffineTransformMakeScale(1, 1)];
view.frame = startFrame;
[self addSubview:view];
if(completionBlock)
completionBlock();
}];
}
And to use them:
# your did select item at index path:
self.itemDetails = [self.storyboard instantiateViewControllerWithIdentifier:#"ItemDetailsVC"];
ItemDetailsVC* itd = [self.storyboard instantiateViewControllerWithIdentifier:#"ItemDetailsVC"];
__weak UIViewController* wself = self;
[self.view addSubView:self.itemDetails.view animateFromPoint:self.zoomedFrom zoomableView:self.itemDetails.viewZoomable minScale:CGSizeMake(0.371134, 0.371134) completion:^{
[wself.navigationController pushViewController:itd animated:NO];
}];
self.addSubviewIsUp = YES;
# back button of the view you added:
[self.navigationController popViewControllerAnimated:NO];
# viewdidapear of your main screen
if(self.addSubviewIsUp){
[self.addVc.view removeFromSuperviewAnimateToPoint:CGPointMake(160, 75) zoomableView:self.addVc.zoomableView minScale:CGSizeMake(0.01, 0.01) completion:^{
}];
}
self.addSubviewIsUp = NO;
Related
How to animate the expansion of a UICollectionViewCell's content upon selection?
Currently I'm using transition animation on my didSelectItemAtIndexPath for animating a view Which isn’t working smoothly like AppStore card animation.
Here is my current code...
AnimateStaticImageViewController *animateImageVC = [[AnimateStaticImageViewController alloc] init];
animateImageVC.modalPresentationStyle = UIModalPresentationFullScreen;
animateImageVC.modelImage = [UIImage imageNamed:text];
[UIView animateWithDuration:0.7 animations:^{
animateImageVC.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 1.3);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.7 animations:^{
animateImageVC.view.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.9, 0.9);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.7 animations:^{
animateImageVC.view.transform = CGAffineTransformIdentity;
}];
}];
}];
[self presentViewController:animateImageVC animated:NO completion:nil];
So, I was trying a modal transition animation in my app's home page staticImageCollectionView immediately after clicking the image.
The core animation & transform mechanism didn't work for me as I need something like AppStore's card animation.
Using this library worked after some hassle! Following this...
Setting the library with following steps.
Calling the transitioningDelegate of the animationViewController on didSelectItemAtIndexPath (or prepareForSegue if working with segue-navigation controller).
Calling it within a completion block to ignore flickering & delay issue in view presentation.
AnimatedStaticImageViewController *animateImageVC = [[AnimatedStaticImageViewController alloc] init];
animateImageVC.modalPresentationStyle = UIModalPresentationFullScreen;
animateImageVC.modelImage = [UIImage imageNamed:text];
[UIView animateWithDuration:0.2
animations:^{
animateImageVC.transitioningDelegate = self;
} completion:^(BOOL finished) {
[self.view removeFromSuperview];
[self presentViewController:animateImageVC animated:YES completion:nil];
}];
Be careful when setting imageView which is the main presentation of the animation.
Make sure you declaring the delegate 'RMPZoomTransitionAnimating' & 'RMPZoomTransitionDelegate' methods on both fromViewController and toViewController.
My goal is simple and I have achieved this previously which is why I'm resorting to asking my question here.
I am trying to animate a subview. Simple enough. The view ends up exactly where I want it to be after the animation is over. The only problem is:
whatever I do the animation duration is completely ignored. It happens instantly.
- (void)callToDismissView:(UIView *)view {
[self.view addSubview:view];
[self dismissViewControllerAnimated:NO completion:nil];
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^(void){
CGRect frame = self.view.frame;
frame.origin.x = frame.size.width;
view.frame = frame;
} completion:^(BOOL finished){
[view removeFromSuperview];
}];
}
Now I have tried different frames and durations to see if the view was animated at all and it always ends up where I need it to be. Only instantly...
EDIT:
The above code is being called by a delegate in the dismissed view controller like so:
- (void)dismissSelf {
if (self.delegate && [self.delegate respondsToSelector:#selector(callToDismissScan)]) {
[self.delegate callToDismissScan];
}
}
And that method itself is triggered by a notification.
I must admit that some things are happening during the transition between the two controllers that I don't fully understand. (And I would very much like to understand them...)
You can try
[self.view layoutIfNeeded];
like this
- (void)callToDismissView:(UIView *)view {
[self.view addSubview:view];
[self dismissViewControllerAnimated:NO completion:nil];
[self.view layoutIfNeeded];
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^(void){
CGRect frame = self.view.frame;
frame.origin.x = frame.size.width;
view.frame = frame;
[self.view layoutIfNeeded];
} completion:^(BOOL finished){
[view removeFromSuperview];
}];
}
Maybe you need try like this.
- (void)callToDismissView:(UIView *)view {
[self.view addSubview:view];
CGRect frame = self.view.frame;
frame.origin.x = frame.size.width;
[UIView animateWithDuration:0.3 delay:0.3
options:UIViewAnimationOptionCurveEaseInOut animations:^(void){
view.frame = frame;
}
completion:^(BOOL finished){
[view removeFromSuperview];
//[self dismissViewControllerAnimated:NO completion:nil];//uncomment if need.
}];
}
It seems there was no way in hell I could animate the transition in the presenting view controller and so the simplest way to resolve the issue was to animate the transition in the presented view controller before it is being dismissed.
The way I did this was by casting the delegate to a view controller. It was then easy to add it's view as a sub-view of my presented view controller and animate it like so:
- (void)dismissSelf {
UIView *dummyView = [ScreenCapper captureScreenIn: self];
UIViewController *presentingViewController = (UIViewController *)self.delegate;
[self.view.window addSubview: presentingViewController.view];
[self.view.window addSubview: dummyView];
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^(void){
dummyView.frame = CGRectMake(dummyView.frame.size.width, dummyView.frame.origin.y, dummyView.frame.size.width, dummyView.frame.size.height);
} completion:^(BOOL finished){
if (self.delegate && [self.delegate respondsToSelector:#selector(callToDismissView)]) {
[self.delegate callToDismissView];
}
}];
}
And in the presenting view controller all that was left to do was to dismiss the presented view controller without animations.
- (void)callToDismissView {
[self dismissViewControllerAnimated:NO completion:nil];
}
I want to make an Menu Animation just as shown below.
I need to have UIButtons inside the menu.
How can i achieve this.
for this animation you should set anchor point by default the anchor point position is (0.5,0.5), so can change the anchor point position:
All geometric manipulations to the view occur about the specified point. For example, applying a rotation transform to a layer with the default anchor point causes the layer to rotate around its center. Changing the anchor point to a different location would cause the layer to rotate around that new point.
self.view.layer.anchorPoint = CGPointMake(0,0);
self.view.transform = CGAffineTransformMakeScale(0.001,0.001);
[UIView animateWithDuration:1.0 animations:^{
self.view.transform = CGAffineTransformIdentity;
}];
Please add the follow code on button click:
[UIView animateWithDuration:1
animations:^{
myView.transform = CGAffineTransformMakeScale(1.5, 1.5); }
completion:^(BOOL finished) {
[UIView animateWithDuration:1
animations:^{
myView.transform = CGAffineTransformIdentity;
}]; }];
It will work for you.
Create Super class SuperViewController.m
Add this method
- (void)viewDidLoad {
[super viewDidLoad];
//Here u can set image also in navigation bar
UIBarButtonItem *buttonC = [[UIBarButtonItem alloc]initWithTitle:#"Word" style:UIBarButtonItemStylePlain target:self action:#selector(GeTVAlue)];
[self.navigationItem setLeftBarButtonItem:buttonC];
}
-(void)GeTVAlue{
UIView *paintView=[[UIView alloc]initWithFrame:CGRectMake(-350, -350, 350, 350)];
[paintView setBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:paintView];
[UIView animateWithDuration:1
animations:^{
paintView.transform = CGAffineTransformMakeScale(2.5, 2.5); }
completion:^(BOOL finished) {
[UIView animateWithDuration:1
animations:^{
paintView.transform = CGAffineTransformIdentity;
}]; }];
}
Then Inherit your Super class in your class
#interface TheerdViewController : SuperViewController
If u have any question fill free ask me.
Thnak you
I have set up a custom dialog to appear via a custom segue when a button in a container view controller is pressed, the perform function is being called and everything appears to work just fine except for the animation.
Here is the segue on the storyboard:
Here is the button:
Here is the code for the segue:
#import "TimerDialogSegue.h"
#implementation TimerDialogSegue
-(void)perform
{
UIViewController *dst = [self destinationViewController];
//Doesn't appear work with the Timer View Controller as the source
// so I use the parent Home View Controller
UIViewController *src = [self sourceViewController];
src = src.parentViewController;
// set the view frame
CGRect frame;
frame.size.height = src.view.frame.size.height;
frame.size.width = src.view.frame.size.width;
frame.origin.x = src.view.bounds.origin.x;
frame.origin.y = src.view.bounds.origin.y;
dst.view.frame = frame;
// add the view to the hierarchy and bring to front
[src addChildViewController:dst];
[src.view addSubview:dst.view];
[src.view bringSubviewToFront:dst.view];
[UIView animateWithDuration:0.3f
animations:^
{
dst.view.alpha = 1.0f;
}];
}
#end
Here is the code from the Dialog that dismisses it, this part animates just fine
- (IBAction)cancelButtonPressed:(id)sender
{
[self dismiss:sender];
}
- (IBAction)dismiss:(id)sender
{
[UIView animateWithDuration:0.3f
animations:^
{
self.view.alpha = 0.0f;
}
completion:^(BOOL finished)
{
[self.view removeFromSuperview];
[self removeFromParentViewController];
}];
}
To summarize the Dialog appears and operates correctly the only issue is there is no animation when it appears. It does animate when it disappears. Anyone know how I might fix this or a workaround to animate this Dialog when it appears?
Thanks in advance for any help.
You are saying:
[UIView animateWithDuration:0.3f
animations:^
{
dst.view.alpha = 1.0f;
}];
But dst.view.alpha is 1 already so nothing happens. You can only animate a change.
For example, when you dismiss, you animate this:
self.view.alpha = 0.0f;
That works because self.view.alpha was 1 so there is actually a change to animate.
I have a View (CupsViewController) with a Label and when it's clicked, TableView (AddressTableController) slides from the bottom of the screen and stays in the lower half.
In TableView, when Ok Buttonis pressed, I want to change value of Labeland remove TableViewwith animation (that is, slide to the bottom).
Here is my code:
CupsViewController
Method called when click on Label
- (IBAction)showPop:(id)sender
{
addressTableController = [[AddressTableController alloc]initWithStyle:UITableViewStyleGrouped];
[addressTableController setDelegate:self];
[[self view] addSubview:[addressTableController myTableView]];
[UIView animateWithDuration:1.0 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
[[addressTableController myTableView] setFrame:CGRectMake(0, kScreenHeight * 0.5, kScreenWidth, kScreenHeight * 0.5)];
} completion:nil];
}
Method called from AddressTableControllerwhen Buttonis pressed
- (void)addressTableController:(AddressTableController *)viewController didChooseValue:(int)value {
direccionLabel.text = [[[[myAppDelegate usuarioActual] cups] objectAtIndex:value] direccion];
[addressTableController.view removeFromSuperview];
}
Image
As you can see, I've tried with removeFromSuperviewbut it does nothing. How can I slide TableViewto the bottom?
It seems that you myTableView property returns a different view, not the one that is referenced in the view property. So you basically add the former as a subview ([[self view] addSubview:[addressTableController myTableView]];), but try to remove the latter ([addressTableController.view removeFromSuperview];).
Just do
[[addressTableController myTableView] removeFromSuperview];
instead of
[addressTableController.view removeFromSuperview];
Here you go. Cheers, mate! :)
P.S.
if you want to animate the view out, you can do it like this
[UIView animateWithDuration:1.0 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
// animation code...
} completion:^(BOOL finished) {
[[addressTableController myTableView] removeFromSuperview];
}];