How can blurriness of UIVisualEffectView be modified while dragging in iOS? - ios

Currently, I'm using a UIVisualEffectView to apply a blur to an image.
I have a UIScrollView. As I pull down on the scrollView, in my "scrollViewDidScroll" method, I'm changing the alpha of the UIVisualEffectView. The current behavior of this is that the blur radius changes smoothly as I drag around in the view.
The problem is, of course, I'm not supposed to be doing this. Getting warnings about changing the alpha value of a UIVisualEffectView.
I've seen people say to do a smooth transition of blurring using an animation, like this here: How to fade a UIVisualEffectView and/or UIBlurEffect in and out?
However, I haven't seen anything that allows me to do this during, say a pan-gesture or something. I mean, if I set up an animation with a timed amount, all good. But doing this during a drag?

There is a way :)
As you've noticed, you can animate from a nil effect to an effect like UIBlurEffectStyleDark so if we add an animation and then pause the layer's animations we can control the progress of the effect by adjusting the layer's timeOffset!
- (void) setupBlur {
// Setup the blur to start with no effect
self.blurredEffectView = [[UIVisualEffectView alloc] initWithEffect:nil];
// Add animation to desired blur effect
[UIView animateWithDuration:1.0 animations:^{
[self.blurredEffectView setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
}];
// Pause layer animations
self.blurredEffectView.layer.speed = 0;
}
Adjust blur between 0.0 and 1.0 (animation duration):
- (void) adjustBlur:(CGFloat)blurIntensity {
self.blurredEffectView.layer.timeOffset = blurIntensity;
}
Note: this won't work on iOS 8 where UIBlurEffect animations aren't supported.

Related

Adding an animatable blur to a view while keeping the background dynamic

I'm trying to implement a custom blur view where the blur radius can be animated, and the blur view can stack blending modes (CGBlendingMode or a CIFilter), all while preserving any animations/actions occurring in the background.
I tried UIVisualEffectView first, but the radius cannot be animated without accessing private APIs which would most likely lead to an app rejection.
The problem with taking a snapshot and applying the effects is that the view is static, and any movement in the background is covered up by the blur view.
I also took a look at FlexMonkey's Blurable, but I had similar results as the snapshot.
Any guidance would be really helpful.
Cheers
Edit: I added a gif to demonstrate what I'm trying to make. The red view moving left to right blurs and multiplies the content below it, while showing the animation occurring on the red/blue square behind it.
Blend modes are extremely tricky and I'm not sure it's possible to apply them to a live UIView (GPUImage might help here) but animating the blur radius (between 0 and UIVisualEffectView's full blur) is possible via this method:
You can animate from a nil effect to an effect like UIBlurEffectStyleDark so if we add an animation and then pause the layer's animations we can control the progress of the effect by adjusting the layer's timeOffset!
- (void) setupBlur {
// Setup the blur to start with no effect
self.blurredEffectView = [[UIVisualEffectView alloc] initWithEffect:nil];
// Add animation to desired blur effect
[UIView animateWithDuration:1.0 animations:^{
[self.blurredEffectView setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
}];
// Pause layer animations
self.blurredEffectView.layer.speed = 0;
}
Adjust blur between 0.0 and 1.0 (animation duration):
- (void) adjustBlur:(CGFloat)blurIntensity {
self.blurredEffectView.layer.timeOffset = blurIntensity;
}
Note: this won't work on iOS 8 where UIBlurEffect animations aren't supported.

Objective c UIImageView animation

I am trying to take a UIImageView and hide it gradually from bottom to top.
What is the best and most efficient way to do it in Objective-C?
I am looking into CABasicAnimation Class and Animation Class.
If you want know CoreAnimation deeply, I think you can use this:
CABasicAnimation *animationA=[CABasicAnimation animation];
animationA.keyPath=#"position.y";
animationA.fromValue=#0;
animationA.toValue=#250;
animationA.duration=3;
animationA.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
[yourTestView.layer addAnimation:animationA forKey:#"basic"];
yourTestView.layer.position=CGPointMake(250, 50);
or if you want to only support IOS7, you can try learn UIAttachmentBehavior and UIDynamicItemBehavior to achieve more interactive animation.
All animations like this use Core Animation and can be done really simply using the block based animations.
For this you would do something like...
[UIView animateWithDuration:3
animations:^{
imageView.frame = CGRectMake(//the end frame of the image view
}];
This will then animate the change over the duration given. (3 seconds in this case).
There are other versions that you can find in the docs of UIView that give you more options like changing the animation curve or running some code on completion etc...
NOTE
This assumes you are not using Auto Layout. If you are using auto layout then the method is exactly the same but you need to change the constraints and then run [view layoutIfNeeded]; in the animations block.

Is it possible to perform a dissolve animation but control the progress, such as how you can with alpha?

I want to dissolve one UIImageView into another, but control the progress (so it occurs as the user pans their finger). This is simple with alpha, as I just change the UIView's alpha value as the user pans, but I don't know how to do it for a dissolve animation, which is slightly different from alpha changing.
Dissolve animation between two images can be made by placing one image on top of other and reducing alpha of the topmost image. This can be done in animation block.
In case of changing dissolve according to user's pan gesture can be written method like:
- (void)setDissolveState:(CGFloat)state
{
self.imageTop.alpha = 1.0 - state;
// ensure bottom image is opaque, this can be done once
self.imageBottom.alpha = 1.0;
}
Here imageTop and imageBottom are UIImage's properties of the object (for example of the view controller) who processes pan events. When change in pan is discovered the method setDissolveState: should be called with relative position of the touch:
CGFloat relativePosition = (touchLocation.x - self.view.frame.origin.x) / self.view.frame.size.width;
[self setDissolveState:relativePosition];

Change the axis of rotation when using UIViewAnimationOptionTransitionFlipFromRight

I'm using
[UIView transitionWithView:duration:options:animations:completion:]
with option
UIViewAnimationOptionTransitionFlipFromRight
for a card flip, but the axis of rotation is the centre of the card. Is it possible to change that axis of rotation to the left edge?
This is not possible using this methods. If you want to do more tricky animation, you should use CoreAnimation explicit animations with 3D transform.
CoreAnimation programming guide
When you'll click to change the view you'll trigger the animation and then when the animation finished you change your views with no animation.
Let's say you have two cards
MyCardView *cardBack;
MyCardView *cardFront;
The shift method should be something like that :
-(void)switchView {
cardBack = [self methodToPrepareContentOfBackCard];
[self myCustomMethodToAnimateCardWithFlip];
}
When the animation is complete you'll use the delegate to set :
cardFront = [cardBack release];
[cardBack release];

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