iOS - properly animate between two UIViews using CATransition - ios

I have a UIView already on my screen and i wish to "slide in" a new UIView from one of the four directions(left, right, up, down) depending on what kind of swipegesture that i detect. Getting the swipegesture info is already done and not a problem but now, lets say if I swipe to the left then i want another UIView instance to "slide in" from the right.
Specifically, as the new UIView is sliding in from the right, the old UIView starts to slide out of view sliding to the left until it is out of the view completely. In other words, i would like to have the effect taht you can see both UIViews during the animation until the original UIView is no longer visible. The same type of effect can be seen on your iPad, for example, as you are on your home screen and you swipe to the left - which slides in another screen of app icons from the right as your home screen slides out of view to the left. The only caveat that I would like to achieve would be that you cannot stop the transition midstream.
Anyway here is the code that i have so far - I think that i am close but would like to get some help on perhaps finishing what i need to accomplish here:
UIView *newView = [[UIView alloc] init];
newView.frame = CGRectMake(0, 0, TileView.frame.size.width, TileView.frame.size.height);
[TileView addSubView:view];
CATransition *transitionAnimation = [CATransition animation];
[transitionAnimation setDuration:1];
[transitionAnimation setType:kCATransitionPush];
[transitionAnimation setSubtype:kCATransitionFromRight];
[transitionAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
The UIView TileView is a subview of my viewController. Is there any other setting up to do for newView so that everything matches as far as screen placement? I think that the KCATransitionPush is the type of animation I am looking for but not 100% sure.
Any help to what I am missing here would be helpful.

try to set these two property also....
transitionAnimation.fromValue=[NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0.0, 0.0, 0.0)];
transitionAnimation.toValue=[NSValue valueWithCATransform3D:CATransform3DMakeTranslation(excursion, 0.0, 0.0)];

Related

view loading from the bottom doesn't fill whole view

I am using this code to load a view when I touch a button in Xcode.
UIStoryboard *storyboard = self.storyboard;
UIViewController *svc = [storyboard instantiateViewControllerWithIdentifier:#"FirstCar"];[self presentViewController:svc animated:YES completion:nil];
The view loads from the bottom, which I wish it didn't but loaded from the side instead. The main problem is that when it finish loading there is a gap at the top of about 1/2 inch. I have used this code to load it above the top depending screen size.
backgroundView = [[UIImageView alloc] initWithFrame:CGRectMake(-20, -20, 454, 776)];
It used to work ok but now for some reason it doesn't. And when I top/hold on an object to move it using "DragView", the object moves jerkily but the whole view moves up and down. I can even make the views contents completely disappear by swiping down. It doesn't go the the previous view just totally blank black. I don't know if that is related but something is weird.
Does anyone have any ideas what I am doing wrong.
Thanks in advance.
What you are describing is the default behavior of a presented view controller in iOS 13 - presented VCs slide in from the bottom and leave a gap at the top (indicating that the user can dismiss by dragging down).
You can remove the gap (and swipedown behavior) by setting the presented VC's modalPresentationStyle to fullscreen like this:
svc.modalPresentationStyle = UIModalPresentationFullScreen;
Add that line before calling present (or you can set that value in your storyboard) and you should see it cover the screen. You can find documentation of other presentation styles in the Apple docs
As for the right-to-left animation you mentioned, a sideways slide in is usually associated with UINavigation controller pushes rather than modal presentations, but as mentioned in this post, you can achieve the sideways animation on a modal using a custom transition.
Here's the relevant code in that post:
CATransition *transition = [[CATransition alloc] init];
transition.duration = 0.5;
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[transition setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[self.view.window.layer addAnimation:transition forKey:kCATransition];
[self presentViewController:svc animated:false completion:nil];

UIView Components Not Moving With View

I have created a UIView in a storyboard. See here for more information. My issue is when the user "logs in" then I present a new view bringing it from the left side of a screen and the main view slides off to the left, like a push navigation, but all programmatically.
So I have decided to animate this "navigation" using the following code.
view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
view.backgroundColor = [UIColor whiteColor];
//add stuff to view
[view addSubview: label];
view.frame = CGRectMake(320, 0, 0, 480);
view.clipsToBounds = YES;
[self.view addSubview:view];
//show view
[UIView animateWithDuration:.5
animations:^{
self.view.frame = CGRectMake(0,0,0,480); //move self.view off left
view.frame = CGRectMake(0, 0, 320, 480); //move new view in place
}];
My view is being successfully displayed but the existing view, self.view is not going off the left side of the screen like I want it. It moves, but it doesn't take it's components with it... When I comment out //view.frame - CGRectMake(0,0,320,480); inside the animation, so I don't display the new view I get this in the simulator on login.
The white background of the view leaves the screen but the components do not. This causes an issue because when I put the two together it does not look like the "new view" is replacing the old view like a navigation push controller but instead sliding over it. Is there a way to move these components with the self.view when I move it off the screen
Thanks for the help!
I am not sure if you can move self.view. Even if it is possible, it's not a good idea...
Anyway your code
self.view.frame = CGRectMake(0,0,0,480);
doesn't slide the view. It scales the view into a zero-width rectangle, which explain why its subviews are still there. By default subviews are aligned to top-left corner of their superviews, and since self.view's top-left hasn't moved (still (0, 0)), they remain the same. The proper way to slide a view off the screen is:
self.view.frame = CGRectMake(-320,0,320,480); // width & height MUST remain unchanged
Still, this will NOT work, since you have made view a subview of self.view... which means this line:
view.frame = CGRectMake(0, 0, 320, 480);
will set view.frame relative to self.view which now has been slided off the screen! So they will be both gone. Another good reason why you shouldn't play with self.view.frame.
IMHO, you should create a view v1 as the main view, and v2 the view that appears when logged in. Make them both subviews of self.view, hide v2 behind v1 and when user logs in, slide v1 off the screen as described above. Or maybe put v1 to the right of v2, and slide them both (so v1 will be sliding out why v2 sliding in, similar to a navigation controller).

UIView sliding transition fades

I've got some code inside one of my view controllers that will make sliding transition from one view to another:
-(void)transitionToNewView:(UIView*)newView
{
UIView *superView = [self.view superview];
[superView addSubview:newView];
newView.frame = superView.bounds;
[self.view removeFromSuperview];
CATransition *animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[superView layer] addAnimation:animation forKey:#"keygoeshere"];
}
The sliding transition seems to work correctly, but I'm also seeing the new view fade in from a blank screen in addition to the sliding. I suspect that this is because I'm adding a new view to the super view that wasn't there before. What I'd like to do is the same thing, but without the fading in. How can I do this?
I think the kCATransitionPush transition does a fade at the same time by design. I could swear I remember reading that somewhere.
It would be pretty simple to construct a view-to-view push transition using the method transitionFromView:toView:duration:options:completion:.
Pass in UIViewAnimationOptionTransitionNone for the transition option, and then use an animation block that slides the current view off-screen while sliding the new view on-screen from the opposite direction.
I don't have a straight answer to your issue but one way I found out for handling transition between two views is to add the new view to your superview like you did, take a screenshot of each view, realize the animation and remove the two screenshots views when the transition is done. I explained more in detail what i did here and it works very well. I think it worth a try to resolve the problem you are facing. Any reason otherwise you don't use the animateWithDuration method on UIView?

iOS - CATransition and transitionWithView issues

Whenever I use either CATransition or transitionWithView to "push" one view from the right, there is a brief moment where the view that's getting pushed in fades in from black (or whatever the background color is), and the view that's getting pushed away fades out to black.
This might be the intended effect, but it looks messy on my app, and was wondering if anyone knows of a way to prevent this "fade out/in" effect?
Here is the CATransition code I am using to present the new view:
myView = [[MyView alloc] initWithNibName:#"MyView" bundle:nil];
[myView setDelegate:self];
[[mainView layer] addAnimation:pushRightTransition forKey:nil];
// Add the view:
[mainView addSubview:[myView view]];

Animating a view on and off the screen in iOS

I am trying to create a list of data displayed to the user. When they click the next or previous button, or swipe on the scrollview, the view should transition off the screen from left to right or right to left depending on which button they press or the direction they swipe. I have it working except that the view slides across the whole screen (meaning it slides over top of the buttons).
Here is the code to do the transition. My scrollview is just a plain old view, but it is in the middle of the page, It's coordinates are (40,54,240,311) so I would like it to disappear at 280 and reappear at 40. Like I said, it currently comes onto the screen at 0 and exits the screen at 320 (in normal portrait mode).
//Animate the scrollview across the screen
CATransition* animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[self.scrollView layer] addAnimation:animation forKey:nil];
I would really like this to work like the Kindle App on the iPhone, where the user can drag the view left or right to show the next page. I have looked into maybe making it a scroll view. So the above code slides my scrollview across the screen, and inside my scrollview I simply have some label and an image I set.
//set the content of the screen
self.imageView.image = [UIImage imageNamed: #"image1.png"];
self.labelNumber.text = #"1";
self.labelText.text = #"Test";
A few initial ideas I have are that I need two scrollviews, and I have to transition between them, or I should make one really wide scrollview and have the data for the next or previous fact to the left or right. But both of these seem to be bad because I have to have a bunch of duplicate controls, outlets etc on the screen.
PS this is my first time posting on this site. woot.
You need to create a new blank UIView that is the super view of your scroll view and the same size as your scroll view. Then you need to call clipsToBounds:YES on this new super view.
Something like:
UIView *blankView = [[UIView alloc] initWithFrame:CGRectMake(40, 54, 240, 311)];
[newView setClipsToBounds:YES];
[scrollViewsParentView addSubview:blankView]
UIScrollView *yourScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 54, 311)];
[blankView addSubview:yourScrollView];
Notice the change in coordinates for "yourScrollView"? It's because its parent is now blankView.
Also, I've done your exact idea of using two UIScrollViews to show a transition between them. You have an on screen (showing) UIScrollView and an offscreen (not showing) UIScrollView and then do your animation to show the transition. In this case they would have the same parent (blankView).
You also might want to check out these UIView methods:
animateWithDuration:animations:
animateWithDuration:animations:completion:
animateWithDuration:delay:options:animations:completion:
Hope this answers your question.

Resources