Crossfade multiple UIViews without background peeking through alpha? - ios

I need to crossfade from one set of views to another set of views. There is a background sometimes behind these views. If I do a naive crossfade with animateWithDuration: v1.alpha = 1.0, v2.alpha = 0.0, then during the animation you will briefly see the background, because two views with alpha 0.5 stacked on top of each other don't have a final alpha of 1.0, they have a final alpha of I believe 0.75, hence you can see the background.
There is a UIView method transitionFromView:toView:... that allows you to achieve an ideal cross fade if you specify the animation option CrossDissolve, however, this method fails if you run two of them at once, even on fully separate views, which is a requirement. That is, if I start transitionFromView from A to B, and then transitionFromView from C to D right after, the first one will crap out.
Is there another way to achieve a proper crossfade that won't break? Does CoreAnimation have any libraries for proper crossfading? Or is there some trickery I can use to achieve it with regular UIView animations?

I assume v1 is above v2 (after it in the subviews array if they have the same parent), and you want v1 to appear and v2 to disappear.
There's no need to animate the alpha v2 at all. Just animate the alpha of v1 from 0 to 1. When the animation ends, you can set v2's alpha to 0 if you want, and remove it from the view hierarchy.
[UIView animateWithDuration:0.2 animations:^{
v1.alpha = 1;
} completion:^{
v2.alpha = 0;
[v2 removeFromSuperview];
}];

This is how you cross dissolve between two views:
UIView.transition(from: fromView, to: toView, duration: 0.3, options: .transitionCrossDissolve) { (_ finished) in
// Completion block here
}

Related

box flip 3D animation for side menu

I have scrollview and inside scrollview I have 2 views as MainView and another as SideMenuView.
What I want to make animation like below.
Any idea what needs to be done to get this working?
Psuedo Code below:
- (void)animateSideMenu{
homeView.frame = CGRectMake(sideMenuWidth, 0.0, (self.view.frame.size.width - sideMenuWidth), self.view.frame.size.height);
[UIView animateWithDuration:1.0 delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
sideMenu.frame = CGRectMake(0.0, 0.0, sideMenuWidth, sideMenuHeight);
[self flipAnimation];
} completion:^(BOOL finished) {
}];
}
- (void)flipAnimation{
CABasicAnimation *yRotate = [CABasicAnimation animationWithKeyPath:#"transform.rotation.y"];
yRotate.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_2, 0, 1, 0)];
yRotate.toValue = #(M_PI * 1.5);
yRotate.duration = 0.5;
yRotate.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[sideMenu.layer addAnimation:yRotate forKey:#"yRotate"];
}
Below are the steps to develop this type of animation:
set the frame of homeView(Red colour view) of screen size & add pan gesture to this view.
set frame of sideMenu view in negative x-axis.
Create a responder function for pan gesture recogniser, in this function call the above mentioned animateSideMenu function.
Adjust the animation parameters accordingly.
Try with this & let me know if anything comes up.
I would not use a scrollview but rather a UIPanGestureRecognizer in which I would detect your current "pan offset" and calculate a current fraction of the animation and positions of those two views (let's simplify it so that the menu is view1 and the rest view2).
Then I would simply set an appropriate transform in the .Changed state.
In .Ended state I would see whether the menu is closer to being open or close and create an animation with .toValue set accordingly. You should use CAAnimations or better - Facebook pop animations because you can pause and remove them and the views stay put and not jump to their initial positions (as is often the case with UIViewAnimate).
If you need help with writing exact code you can write here and I'll edit my answer.
There's tutorial for exactly that menu, though it's in Swift:
https://www.raywenderlich.com/87268/3d-effect-taasky-swift

UIView continuous animation that repeats using a different frame iOS

I am doing an animation on a UIView and having it repeat, which is working well like so:
[UIView animateWithDuration:6.0f delay:0.0f options:UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveEaseIn animations:^{
self.imgTopCloud.frame = CGRectMake(-self.imgTopCloud.frame.size.width, self.imgTopCloud.frame.origin.y, self.imgTopCloud.frame.size.width, self.imgTopCloud.frame.size.height);
}completion:nil];
This animates it outside of the view's bounds. Now, when it does that, I want the imgTopCloud's frame to start right at the very end of the view like this:
//Now we start at the very right
self.imgTopCloud.frame = CGRectMake(self.view.frame.size.width, self.imgTopCloud.frame.origin.y, self.imgTopCloud.frame.size.width, self.imgTopCloud.frame.size.height);
The issue is, when the animation starts to repeat, it brings it back to imgTopCloud's original starting frame, not the new one I want. I tried putting the new frame in the completion block of the animateWithDuration message, but no dice.
Any ideas?
Don't repeat that animation. Instead, in the completion block of that animation, you need to do two things.
1) set the frame to the very right
2) start a repeating animation that moves the view to the left

Circular animation to make UIImageView appear

I have a "circular" image, something like a pie chart. I would like a nice appearing animation, like when a pie chart fills itself from 0 to the value.
I usually use something like this when I want to animate views :
[UIView animateWithDuration: 3.0
delay: 0.0
options: UIViewAnimationCurveEaseInOut
animations: ^ {
// The animation
}
completion: ^(BOOL finished) {
// On completion
} ];
Is it possible to do the same thing for a circular animation ? I really have no idea on how to do that.
Thanks for any leads !
Note : iOS 5, storyboards, ARC, and all that stuff :)
Edit : for future discussion, the image looks like this :
Okay, here it goes :)
First option (Easy one). You could use UIImageView's animationImages property. Make NSArray with animation images (in your case, circular images those fill from 0 to full circle), set animationDuration, and call [imageView startAnimating] (I'm assuming that your UIImageView is imageView), and you can call [imageView stopAnimating] when process is done.
Second:
Check out this link http://www.cocoacontrols.com/platforms/ios/controls/jpradialactivityindicator, I think that sample project does the almost same, as you are trying to do :)
Good Luck ;)
1) You can use CAShapeLayer
You can achieve it by animating the strokeStart and strokeEnd properties. You could create the path for the full circle and use the strokeStart and strokeEnd properties to only stroke a certain part of the circle.
2) Also, you can refer to this tutorial : Animating Pie Slices Using a Custom CALayer
Good Luck!!!

How to replace one UI element by another with custom animation?

I want to implement nested commentaries(like stickers) in my own document viewer.
At first, it should be UITextView, but when resignFirstResponder executes, it should become just a small button.
The main question is: how to animate this?
I've read Quartz 2d programming guide from Apple, but it didn't gave me any ideas.
I don't asking for exact or ready solution: keywords, links to articles or documentation are enough.
Thanks for future responses.
You could use this method
[UIView animateWithDuration: delay: options: animations: completion:];
So if you wanted to fade in a button and fade out the textfield it would be
//Starting properties
myButton.alpha = 0;
myTextField.alpha = 1;
//Do the animation
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
myButton.alpha = 1;
myTextField.alpha = 0;
} completion:^(BOOL finished) {
if (finished) {
NSLog(#"finished animating");
}
}];
This will change the opacity of the 2 objects from 0 - 1 / 1 - 0 over 300ms
You can animate many properties this way like size, position, opacity etc.
You could do it the same way that Apple fades between two different elements in QuickLook. You can see the effect yourself in slow-motion by pressing shift+space with an item selected in Finder.
The animation basically is a cross-fade at the same time that the frame changes. You should probably render both the button and the text view into images and do the animation with two image views (that only exist during the animation) to be able to stretch the images as the aspect ratio changes when the frames change.
You will need Core Animation to render the views into images but the rest of the images are only frame and alpha/opacity animations so you should be able to do them with UIView animations (if Core Animation seems to complicated for you). Though Core Animation will give you some more fine grained control when it comes to tweaking the animation.

ios MapKit MKOverlayView animation happening instantly

I am trying to animate the alpha value of a MapKit overlay view (specifically an MKCircleView) in iOS 5 using the following code:
-(void) animateCircle:(MKCircle*)circle onMap:(MKMapView*) mapView
{
MKCircleView * circleView = (MKCircleView*) [mapView viewForOverlay:circle];
UIViewAnimationOptions options = UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionTransitionNone;
[UIView animateWithDuration:5.0
delay:0.0
options:options
animations:^(void) { circleView.alpha = 0.9; }
completion:^(BOOL finished) {}
];
}
The alpha value of the overlay is changing as I want, but it is jumping there instantaneously rather than animating over the specified duration.
Can anyone suggest what might be wrong? Perhaps animation on overlay views os more complex with blocks than I had thought.
Core Animation has interesting behavior when concurrent animations effect the same view... If you try to animate a view before the view's last animation finished, it will assume you intended the subsequent animation to start from the desired end-state of the initial one. This can result in jumps of frames as well as jumps of alpha values.
In your case, this view is likely being animated by something else. Try locating and removing the other animation / or'ing in UIViewAnimationOptionBeginFromCurrentState to its options.

Resources