iOS Button not clickable during animation - ios

When I added animation to my button using a category method, then I can't click that button, seems it is disabled:
[_compassCalibrateButton pulse:1.5 continuously:YES];
_compassCalibrateButton.userInteractionEnabled=YES;
I have a UIView category contatining this :
- (void)pulse:(float)secs continuously:(BOOL)continuously {
[UIView animateWithDuration:secs/2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
// Fade out, but not completely
self.alpha = 0.3;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:secs/2
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
// Fade in
self.alpha = 1.0;
}
completion:^(BOOL finished) {
if (continuously) {
[self pulse:secs continuously:continuously];
}
}];
}];
}

From the doc
During an animation, user interactions are temporarily disabled for
the views being animated. (Prior to iOS 5, user interactions are
disabled for the entire application.) If you want users to be able to
interact with the views, include the
UIViewAnimationOptionAllowUserInteraction constant in the options
parameter.
So your code should be
- (void)pulse:(float)secs continuously:(BOOL)continuously {
[UIView animateWithDuration:secs/2
delay:0.0
options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
animations:^{
// Fade out, but not completely
self.alpha = 0.3;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:secs/2
delay:0.0
options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
animations:^{
// Fade in
self.alpha = 1.0;
}
completion:^(BOOL finished) {
if (continuously) {
[self pulse:secs continuously:continuously];
}
}];
}];
}

I tested on Swift 4
UIView.animate(withDuration: 0.8, delay: 0, options: [.repeat, .autoreverse, .allowUserInteraction], animations: {
// Do Something
}, completion: nil)

Try this it will help you
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:self.view];
for (UIButton *button in self.arrBtn)
{
if ([button.layer.presentationLayer hitTest:touchLocation])
{
// This button was hit whilst moving - do something with it here
[button setBackgroundColor:[UIColor cyanColor]];
NSLog(#"Button Clicked");
break;
}
}
}

Note that if you are animating a UIButton to fade out after a while, e.g.:
[UIView animateWithDuration:1.0 delay:3.0 options:|UIViewAnimationOptionAllowUserInteraction animations:^{
self->btn.alpha = 0;
} completion:nil];
It will be unresponsive from the very start, regardless your 'delay', due to the final alpha. One way around this is something like:
[UIView animateWithDuration:1.0 delay:3.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
self->btn.alpha = 0.1;
} completion:^(BOOL finished){self->btn.alpha = 0;}];

Related

Create A Shadow(or blur) when user Click on UIbutton?

I have a One Uibutton in Buttom. when User click on that button a uiview animation is display like popup from buttom to up.
this is my code
-(void)viewDidLoad
{
[super viewDidLoad];
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 1000, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
}
- (IBAction)animated:(id)sender
{
if(_isAnimated)
{
[UIView animateWithDuration:0.3
delay:0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 520, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
}
completion:^(BOOL finished){
}];
_isAnimated=NO;
}
else
{
[UIView animateWithDuration:0.3
delay:0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 1000, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
}
completion:^(BOOL finished)
{
}];
_isAnimated=YES;
}
}
Uiview animation is perfectly working but when uiview appear than background view is create shadow(or blur)like uiactionsheet and after finished animation background view is clear.
i dont know how to implemented.
plz help me
i am new in ios...
You can add a UIView in background and set its backgroundcolor black and alpha 0.5 in storyboard. Then change its alpha from 0.5 to 0 with animation. You can also add an UITapGestureRecognizer to detect taps on it and dissmiss the view when user taps outside.
-(void)viewDidLoad
{
[super viewDidLoad];
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 1000, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
}
- (IBAction)animated:(id)sender
{
if(_isAnimated)
{
[UIView animateWithDuration:0.3
delay:0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 520, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
//showing background view here
self.viewBackground.alpha = 0.5;
}
completion:^(BOOL finished){
}];
_isAnimated=NO;
}
else
{
[UIView animateWithDuration:0.3
delay:0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 1000, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
//dismissing background view here
self.viewBackground.alpha = 0.0;
}
completion:^(BOOL finished)
{
}];
_isAnimated=YES;
}
}
For detecting taps outside and dismissing your view:
Create a UITapGestureRecognizer:
#interface ViewController ()
{
UITapGestureRecognizer *tapGesture;
}
Initialize it in ViewDidLoad:
-(void)viewDidLoad
{
//defining your gesture method
tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handleSingleTapGesture:)];
//adding gesture recognizer on the background view
[self.backgroundView addGestureRecognizer:tapGestureRecognizer];
}
In your Gesture Recognizer Method:
-(void)handleSingleTapGesture:(UITapGestureRecognizer *)tapGestureRecognizer
{
[UIView animateWithDuration:0.3
animations:^{
//dismissing background view here
self.viewBackground.alpha = 0.0;
}
completion:^(BOOL finished){
}];
}
Hope this helps.
add your code in viewdidload.add QuartzCore framework
#import <QuartzCore/CAAnimation.h>
self.BuyButtonPopUpView.frame = CGRectMake(self.BuyButtonPopUpView.frame.origin.x, 1000, self.BuyButtonPopUpView.frame.size.width,self.BuyButtonPopUpView.frame.size.height);
CABasicAnimation *animate = [CABasicAnimation animationWithKeyPath:#"shadowOpacity"];
animate.fromValue = [NSNumber numberWithFloat:1.5];
animate.toValue = [NSNumber numberWithFloat:0.5];
animate.duration = 1.0;
[self.BuyButtonPopUpView.layer addAnimation:animation forKey:#"shadowOpacity"];
self.BuyButtonPopUpView.layer.shadowOpacity = 0.0;
you can add a UIVisualEffectView first then add the popup over this view.
here is a tutorial link https://www.raywenderlich.com/84043/ios-8-visual-effects-tutorial

Continous fade in and fade out

Im trying to fade in and out of a light node I have created I just dont know where to call the function accordingly so it will continously fade in and out. Never tried animating anything here is what I have.
- (void)fadeOutIn:(UIView *)view duration:(NSTimeInterval)duration
{
[self enumerateChildNodesWithName:#"//*" usingBlock:^(SKNode *node, BOOL *stop) {
if ([node.name isEqualToString:#"light1"]) {
[UIView animateKeyframesWithDuration:5 delay:2 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse|UIViewAnimationCurveEaseInOut animations:^{
node.alpha = 0;
} completion:^(BOOL finished) {
}];
}
}];
}
where should I call this function?that is fades in and out continously?
Should it be called within an action?
Thank You
Use this for Continue fade in out.
-(void)viewDidAppear:(BOOL)animated{
[UIView animateKeyframesWithDuration:1 delay:0 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse|UIViewAnimationCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction animations:^{
node.alpha = 0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:1 animations:^{
node.alpha = 1;
} completion:nil];
}];
}
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[objAnimate setAlpha:1.0];
[UIView animateKeyframesWithDuration:2.0 delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeLinear | UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{
[objAnimate setAlpha:0.0];
} completion:nil];
}
This will create continuous fade in and out for your object when it appears. If you want to create programmatically a custom object and then use this code then do it after your custom object is added in your view as below (example):
objAnimate = [[UILabel alloc] initWithFrame:CGRectMake(20, 50, 200, 40)];
objAnimate.backgroundColor = [UIColor lightGrayColor];
[objAnimate setAlpha:1.0];
[self.view addSubview:objAnimate];
[UIView animateKeyframesWithDuration:2.0 delay:0.0 options:UIViewKeyframeAnimationOptionCalculationModeLinear | UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{
[objAnimate setAlpha:0.0];
} completion:nil];
The view starts animating as soon as its added in your view.

Dismiss a view with animation

I am popping the couponDetailsView with bounce animation. But i want to dismiss the view from left to right animation. How can i do this? Below is my source code. Any kind of help would be really helpful.
#pragma mark Bounce Animation
-(void) openContentDetailsView
{
[self.view bringSubviewToFront:self.couponDetailsView];
[UIView animateWithDuration:0.2 animations:
^(void){
self.couponDetailsView.transform = CGAffineTransformScale(CGAffineTransformIdentity,1.1f, 1.1f);
self.couponDetailsView.alpha = 0.5;
}
completion:^(BOOL finished){
[self bounceOutAnimationStoped];
}];
}
- (void)bounceOutAnimationStoped
{
[UIView animateWithDuration:0.1 animations:
^(void){
self.couponDetailsView.transform = CGAffineTransformScale(CGAffineTransformIdentity,0.9, 0.9);
self.couponDetailsView.alpha = 0.8;
}
completion:^(BOOL finished){
[self bounceInAnimationStoped];
}];
}
- (void)bounceInAnimationStoped
{
[UIView animateWithDuration:0.1 animations:
^(void){
self.couponDetailsView.transform = CGAffineTransformScale(CGAffineTransformIdentity,1, 1);
self.couponDetailsView.alpha = 1.0;
}
completion:^(BOOL finished){
[self animationStoped];
}];
}
- (void)animationStoped
{
}
- (IBAction)contentDetailsCloseButtonAction:(id)sender {
self.couponDetailsView.alpha = 0;
self.couponDetailsView.transform = CGAffineTransformScale(CGAffineTransformIdentity,0.6, 0.6);
}
Try this:
[UIView animateWithDuration:0.3f
delay:0.0f
options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse
animations:^{
[testView setFrame:CGRectMake(x, y, width, height)];
} completion:^(BOOL finished) {
[testView removeFromSuperview];
}];

ios show Button with animation show one by one here i add link

I have six button on view with two pair of two grid.The problem is how to show button with animation, here I attach example url how to create this type of animation.
In this example when you click on menu button then show button in side menu view with animation
https://github.com/djardon/SideMenuFrostedAnimated
I tried this but I can't get any success.
I have two button one is btnHome and second is btnAbout:
-(void)animationStart
{
[btnHome setAlpha:0.f];
[UIView animateWithDuration:1.f delay:0.f options:UIViewAnimationOptionCurveEaseIn animations:^{
[btnHome setAlpha:0.f];
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
[btnHome setAlpha:1.f];
[self animationStart2];
} completion:nil];
}];
}
-(void)animationStart2
{
[btnAbout setAlpha:0.0f];
//fade in
[UIView animateWithDuration:2.0f animations:^{
[btnAbout setAlpha:1.0f];
} completion:^(BOOL finished) {
//fade out
[UIView animateWithDuration:2.0f animations:^{
[btnAbout setAlpha:0.0f];
} completion:nil];
}];
}
Try this.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
btnHome.alpha=0.0;
btnAbout.alpha=0.0;
}
-(void)animationStart
{
[UIView animateWithDuration:0.4f delay:0.0f options: UIViewAnimationOptionCurveEaseInOut animations:^{
btnHome.alpha=1.0;
} completion:^(BOOL finished) {
[self animationStart2];
}];
}
-(void)animationStart2
{
[UIView animateWithDuration:0.4f delay:0.0f options: UIViewAnimationOptionCurveEaseInOut animations:^{
btnAbout.alpha=1.0;
} completion:^(BOOL finished) {
}];
}
- (IBAction)btnClick:(id)sender
{
[self animationStart];
}
Here initially i am setting the buttons alpha value to 0.0f. On click of third button i am showing these two buttons.

Fade In Fade Out Animation

Here is some code I struggle with for a while.
If you start the fade in animation, the label text fades in.
If I start the fade out animation the the label text fades out.
When I start the startFade method, only fade out is shown. How can I wait for the fadeIn method to finish visually before starting the fadeOut method.
-(IBAction)startFade:(id)sender{
[self fadeIn];
[self fadeOut];
}
-(IBAction)fadeIn:(id)sender{
[self fadeIn];
}
-(IBAction)fadeOut:(id)sender{
[self fadeOut];
}
-(void) fadeIn{
[_label setAlpha:0];
[UILabel beginAnimations:NULL context:nil];
[UILabel setAnimationDuration:2.0];
[_label setAlpha:1];
[UILabel commitAnimations];
}
-(void) fadeOut{
[UILabel beginAnimations:NULL context:nil];
[UILabel setAnimationDuration:2.0];
[_label setAlpha:0];
[UILabel commitAnimations];
}
When you call the fadeIn and fadeOut methods back to back like you're doing, the code is run instantaneously, so you'll only see animation from the last method called. UIView block based animation provides a completion handler, which seems to be exactly what you're looking for. So your code might looks something like this:
-(IBAction)startFade:(id)sender {
[_label setAlpha:0.0f];
//fade in
[UIView animateWithDuration:2.0f animations:^{
[_label setAlpha:1.0f];
} completion:^(BOOL finished) {
//fade out
[UIView animateWithDuration:2.0f animations:^{
[_label setAlpha:0.0f];
} completion:nil];
}];
}
Swift:
#IBAction func startFade(_ sender: AnyObject) {
label.alpha = 0.0
// fade in
UIView.animate(withDuration: 2.0, animations: {
label.alpha = 1.0
}) { (finished) in
// fade out
UIView.animate(withDuration: 2.0, animations: {
label.alpha = 0.0
})
}
}
that does the job for you (the _label is your label);
- (IBAction)startFade:(id)sender {
[_label setAlpha:0.f];
[UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveEaseIn animations:^{
[_label setAlpha:1.f];
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
[_label setAlpha:0.f];
} completion:nil];
}];
}
Generic answer : You can use this method to apply animation to any UIView object .
First create an extension of UIView class . Create a separate swift file and write the code like this
import Foundation
import UIKit
extension UIView {
func fadeIn() {
//Swift 2
UIView.animateWithDuration(1.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.alpha = 1.0
}, completion: nil)
//Swift 3, 4, 5
UIView.animate(withDuration: 1.0, delay: 0.0, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.alpha = 1.0
}, completion: nil)
}
func fadeOut() {
//Swift 2
UIView.animateWithDuration(1.0, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
self.alpha = 0.0
}, completion: nil)
//Swift 3, 4, 5
UIView.animate(withDuration: 1.0, delay: 0.0, options: UIView.AnimationOptions.curveEaseOut, animations: {
self.alpha = 0.0
}, completion: nil)
}
}
Here self refers to any UIView you refer to . You can use buttons, labels etc to call these 2 methods .
Then in any other swift class you can call fadeIn() and fadeOut() like this :
self.yourUIObject.fadeIn()
self.yourUIObject.fadeOut()
This gives the desired effect of animation to any UIObject .
Try this..
// Fade Out
-(void)fadeOut:(UIView*)viewToDissolve withDuration:(NSTimeInterval)duration andWait:(NSTimeInterval)wait
{
[UIView beginAnimations: #"Fade Out" context:nil];
// wait for time before begin
[UIView setAnimationDelay:wait];
// druation of animation
[UIView setAnimationDuration:duration];
viewToDissolve.alpha = 0.0;
[UIView commitAnimations];
}
// Fade In
-(void) fadeIn:(UIView*)viewToFadeIn withDuration:(NSTimeInterval)duration andWait:(NSTimeInterval)wait
{
[UIView beginAnimations: #"Fade In" context:nil];
// wait for time before begin
[UIView setAnimationDelay:wait];
// druation of animation
[UIView setAnimationDuration:duration];
viewToFadeIn.alpha = 1;
[UIView commitAnimations];
}
// Fade in from fade out
-(void) fadeInFromFadeOut: (UIView*)viewToFadeIn withDuration:(NSTimeInterval)duration
{
viewToFadeIn.hidden=NO;
[self fadeOut:viewToFadeIn withDuration:1 andWait:0];
[self fadeIn:viewToFadeIn withDuration:duration andWait:0];
}
// Button operation
-(void) buttonClicked :(id)sender
{
NSLog(#"Button clicked");
// Each button is given a tag
int tag = ((UIButton*)sender).tag;
if (tag ==1)
{
sprite.alpha =1;
[self fadeOut : sprite withDuration: 10 andWait : 1 ];
}
else if (tag ==2)
{
sprite.alpha =0;
[self fadeIn : sprite withDuration: 3 andWait : 1 ];
}
else
{
[self fadeInFromFadeOut:sprite withDuration:10];
}
}
View this link to download sample..
Refer this link.
Happy to share with you..:-)
you can do something like this (check possible parameters values and similar methods here :
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html
[UIView animateWithDuration:duration
delay:delay
options:option
animations:^{
//fade in here (changing alpha of UILabel component)
}
completion:^(BOOL finished){
if(finished){
//start a fade out here when previous animation is finished (changing alpha of UILabel component)
}];
}
Based on #holex's answer, but simplified a bit (as commented):
- (IBAction)startFade:(id)sender {
[_label setAlpha:0.f];
[UIView animateWithDuration:2.f
delay:0.f
options:UIViewAnimationOptionCurveEaseIn
| UIViewAnimationOptionAutoreverse
animations:^{
[_label setAlpha:1.f];
}
completion:nil];
}
Swift 4
If you need just one pulse when clicking the button, use that:
#IBAction func didPressButton(_ sender: UIButton) {
self.someView.alpha = 0
UIView.animate(withDuration: 0.4,
delay: 0,
options: [.curveEaseInOut, .autoreverse],
animations: {
self.someView.alpha = 1
},
completion: { _ in
self.someView.alpha = 0
})
}
Swift 5 version of iPhoneDeveloper's answer:
extension UIView {
func fadeIn() {
UIView.animate(withDuration: 1.0, delay: 0.0, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.alpha = 1.0
}, completion: nil)
}
func fadeOut() {
UIView.animate(withDuration: 1.0, delay: 0.0, options: UIView.AnimationOptions.curveEaseOut, animations: {
self.alpha = 0.0
}, completion: nil)
}
}
The easiest way would be to use:
[UIView animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion]
and add the fadeOut call to the completion block. The documentation might help answer any questions you have.
If you can't use the block version for some reason, then you'll have to set a delegate ([UIView setAnimationDelegate:(id)delegate]) and a selector with ([UIView setAnimationDidStopSelector:]) that the delegate will respond to.
Again, see the documentation for more details.
My task was to make a label fade out. And then fade in with changed text. The solution was:
-(void)performAnimationOnHistoryButtonLabelUpdatingTextTo:(NSString *)text
{
[UIView animateWithDuration:0.4f animations:^{
[self.historyButtonLabel setAlpha:0.0f];
} completion:^(BOOL finished) {
self.historyButtonLabel.text = text;
[UIView animateWithDuration:0.4f animations:^{
[self.historyButtonLabel setAlpha:1.0f];
} completion:nil];
}];
}
labelAnimate = (UILabel*) [self.view viewWithTag:101];
btnTapMe = (UIButton*) [self.view viewWithTag:100];
[btnTapMe addTarget:self action:#selector(startAnimating:) forControlEvents:UIControlEventTouchUpInside];
//////////////
-(void) startAnimating:(UIButton*)button {
[labelAnimate setAlpha:0.0];
[NSTimer scheduledTimerWithTimeInterval:1.8 target:self selector:#selector(continuousEaseInOut) userInfo:button repeats:YES];
}
-(void) continuousFadeInOut {
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
[labelAnimate setAlpha:1.0];
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[labelAnimate setAlpha:0.0];
} completion:nil];
}];
}
I strongly suggest you use a generic implementation so you can reuse the code whenever you need the fade effect again.
You should create an UIView extension:
UIView+Animations.h
#import <Foundation/Foundation.h>
#interface UIView (Animations)
- (void)fadeInWithCompletion:(void (^ __nullable)(BOOL finished))completion;
- (void)fadeOutWithCompletion:(void (^ __nullable)(BOOL finished))completion;;
#end
UIView+Animations.m
#import "UIView+Animations.h"
#implementation UIView (Animations)
- (void)fadeInWithCompletion:(void (^ __nullable)(BOOL finished))completion {
[UIView animateWithDuration:2 animations:^{
[self setAlpha:1];
} completion:completion];
}
- (void)fadeOutWithCompletion:(void (^ __nullable)(BOOL finished))completion {
[UIView animateWithDuration:2 animations:^{
[self setAlpha:0];
} completion:completion];
}
#end
So, you only have to import the new file to your class or inside your Prefix.pch and use it like this:
[_label fadeOutWithCompletion:^(BOOL finished) {
[_label fadeInWithCompletion:nil];
}];
Note that you could also use nil as the completion parameter when you have nothing else to do after completion.
I also recommend you do not parameterize the duration to keep a pattern through you entire application.
This implementation can be used in the future for UIButton, UILabel, UITextField... Well, any class derived from UIView.
The fade in and fade out animations can be combined using UIView.animate(withDuration: animations:)
UIView.animate(withDuration: animationDuration, animations: {
myView.alpha = 0.75
myView.alpha = 1.0
})

Resources