Animating annotationViews (loop animation), didSelectAnnotationView doesn't work - ios

So I am trying to animate my annotationViews using the following code :
- (void)mapView:(MKMapView *)mapView
didAddAnnotationViews:(NSArray *)annotationViews
{
LLAnnotationView *aV;
for (aV in annotationViews) {
// Don't pin drop if annotation is user location
if ([aV.annotation isKindOfClass:[MKUserLocation class]]) {
continue;
}
aV.transform = CGAffineTransformMakeScale(0, 0);
aV.alpha = 0.1;
dispatch_async(dispatch_get_main_queue(), ^(void){
[self animateAnnotationView:aV withAnnotationViews:annotationViews];
});
}
}
-(void)animateAnnotationView:(LLAnnotationView*)aV withAnnotationViews:(NSArray*)annotationViews{
#define kDurationBetweenShowUpAnimations 0.4
#define kLoopAnimationDuration 1
#define kAnimationDuration 0.4
// Initial animation
[UIView animateWithDuration:kAnimationDuration delay:kDurationBetweenShowUpAnimations*[annotationViews indexOfObject:aV]options:UIViewAnimationOptionCurveLinear animations:^(void){
aV.transform = CGAffineTransformMakeScale(1.1, 1.1);
aV.alpha = 1.0;
}completion:^(BOOL finished){
[UIView animateWithDuration:kAnimationDuration/2 animations:^(void){
aV.transform = CGAffineTransformMakeScale(1.0, 1.0);
aV.alpha = 0.9;
}completion:^(BOOL finished){
[UIView animateWithDuration:kAnimationDuration animations:^(void){
aV.transform = CGAffineTransformMakeScale(1.1, 1.1);
aV.alpha = 1.0;
}completion:^(BOOL finished){
// **LOOP animation**
[UIView animateWithDuration:kLoopAnimationDuration delay:0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse animations:^(void){
aV.transform = CGAffineTransformMakeScale(1.0, 1.0);
aV.alpha = 0.9;
}completion:^(BOOL finished){
}];
}];
}];
}];
}
Everything works as it should concerning the animation.
But when I try to select an annotation View, didSelectAnnotationView is rarely called.
I suspect that this should be thread related.
Does anyone have a clue what's going on??
Thank you.

Just found the solution. Add UIViewAnimationOptionAllowUserInteraction to the options of animateWithDuration :
[UIView animateWithDuration:kLoopAnimationDuration delay:0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionAllowUserInteraction ...
!!

Related

iOS continuous fade-out and fade-in animation

In objective-c, I want to add fade in and fade out animation to a UIView. I want to do the fade-out and fade-in animation continuously. To illustrate it, what effect I want to have is as following:
fade out - fade in - fade out - fade in - ...
What I'm trying is as following:
-(void)fadeOutIn:(UIView *)view duration:(NSTimeInterval)duration
{
static CGFloat alpha = 1.0;
[UIView animateWithDuration:duration
delay:0.0
options: UIViewAnimationOptionRepeat| UIViewAnimationOptionCurveEaseInOut
animations:^{
alpha = abs((int)(alpha - 1.0));
view.alpha = alpha;
}
completion:^(BOOL finished){
}];
}
I also tried following:
-(void)fadeOutIn:(UIView *)view duration:(NSTimeInterval)duration
{
[UIView animateWithDuration:duration
delay:0.0
options: UIViewAnimationOptionRepeat| UIViewAnimationOptionCurveEaseInOut
animations:^{
view.alpha = 0.0;
}
completion:^(BOOL finished){
[UIView animateWithDuration:duration
delay:0.0
options: UIViewAnimationOptionRepeat|UIViewAnimationOptionCurveEaseInOut
animations:^{
view.alpha = 1.0;
}
completion:^(BOOL finished){
}];
}];
}
But the issue is they worked all the same, i.e., the UIView will fade out properly and SUDDENLY show up(not fade in), then fade out again...
Seems the fade in animation not work at all. Does anybody know what's wrong of my code please? Any suggestion will be highly appreciated.
Try this
[UIView animateKeyframesWithDuration:1 delay:0 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse|UIViewAnimationCurveEaseInOut animations:^{
self.customIV.alpha = 0;
} completion:^(BOOL finished) {
}];
Here's this, Vigor, this does work, but I had to modify the code, this is somewhat dangerous code, due to it's constant recursiion, but you'll get the point:
-(void)fadeOutIn
{
[UIView animateWithDuration:1
delay:0.0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
[[self contentView] emailField].alpha = 0.0;
}
completion:^(BOOL finished){
[UIView animateWithDuration:1
delay:0.0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
[[self contentView] emailField].alpha = 1.0;
}
completion:^(BOOL finished){
[self fadeOutIn];
}];
}];
}
I would really rethink how this works, I used it on a button in my view and it will recurse constanly, until the view is removed from the superview. I had to hardcode the button in the code.
[UIView animateWithDuration:duration
delay:0.0
options: UIViewAnimationOptionRepeat| UIViewAnimationOptionAutoreverse|UIViewAnimationOptionCurveEaseInOut
animations:^{
view.alpha = 0.0;
}
completion:nil];
Just call this once
Try this....
YourView.alpha = 1;// set the initial value of alpha
[UIView animateWithDuration:1 delay:0
options: UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
animations:^{
YourView.alpha = 0; // set the max value of alpha
} completion:nil];
This solution is for Swift 3,4 and 5
UIView.animateKeyframes(withDuration: 1, delay: 0, options: [UIView.KeyframeAnimationOptions(rawValue: UIView.AnimationOptions.repeat.rawValue), UIView.KeyframeAnimationOptions(rawValue: UIView.KeyframeAnimationOptions.RawValue(UIView.AnimationCurve.easeInOut.rawValue)), UIView.KeyframeAnimationOptions(rawValue: UIView.AnimationOptions.autoreverse.rawValue)] , animations: {
self.logoCenterImageView.alpha = 0
}) { finished in
}

automatically Move imageView on screen like L shape iOS

I am trying to move image like L shape in my iOS app.
I have tried this code but it is moving image only in one line that I don't want.
- (void)startApp {
UIImageView *imageToMove =
[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"man.jpg"]];
imageToMove.frame = CGRectMake(10, 10, 100, 100);
[self.view addSubview:imageToMove];
// Move the image
[self moveImage:imageToMove
duration:1.0
curve:UIViewAnimationCurveLinear
x:70.0
y:70.0];
}
- (void)moveImage:(UIImageView *)image
duration:(NSTimeInterval)duration
curve:(int)curve
x:(CGFloat)x
y:(CGFloat)y {
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
image.transform = transform;
// Commit the changes
[UIView commitAnimations];
}
I would recommend something like this:
- (void)animateLikeL
{
[UIView animateWithDuration:1.5f
delay:0.0f
options:UIViewAnimationOptionCurveLinear
animations:^{
self.yourImage.transform = CGAffineTransformMakeTranslation(0.0f, 10.0f);
} completion:^(BOOL finished){
if(finished == NO)
{
return;
}
[UIView animateWithDuration:1.5f
delay:0.0f
options:UIViewAnimationOptionCurveLinear
animations:^{
self.yourImage.transform = CGAffineTransformMakeTranslation(10.0f, 10.0f);
} completion:^(BOOL finished){
if(finished == NO)
{
return;
}
self.yourImage.transform = CGAffineTransformIdentity;
[self animateLikeL];
}];
}];
}
Another attempt is to play arround with self.yourImage.center. Increase center.y to move the image down and then increase center.x to move it left. Hope this helps.
I did it like this: circle is a UIImage view in the interface builder size 70*70 and frame set at (10,10), then stick this code in:
- (void)viewDidAppear:(BOOL)animated {
[UIView animateWithDuration:1
delay:0
options:0
animations:^{
self.circle.frame = CGRectMake(10, 249, 70, 70);
}
completion:^(BOOL finished) {
[UIView animateWithDuration:1
delay:0
options:0
animations:^{
self.circle.frame = CGRectMake(150, 249, 70, 70);
}
completion:^(BOOL finished) {
NSLog(#"Complete");
}];
}];
}
I would just chain the animations.
[UIView animateWithDuration:duration/2 delay:0 options:curve animations:^{
CGAffineTransform transform = CGAffineTransformMakeTranslation(x,0);
image.transform = transform;
} completion:^(BOOL finished) {
[UIView animateWithDuration:duration/2 delay:0 options:curve animations:^{
CGAffineTransform transform = CGAffineTransformMakeTranslation(x,y);
image.transform = transform;
} completion:nil];
}];
This is what I have done......Thank you.
- (void)viewDidLoad
{
[super viewDidLoad];
[self startAppForFirstImg];
[self startAppForSecondImg];
}
//First Image coordinates.
- (void)startAppForFirstImg{
UIImageView *imageToMove =
[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"man.jpg"]];
imageToMove.frame = CGRectMake(180,280,100,100);
[self.view addSubview:imageToMove];
// Move the image
[self moveFirstImage:imageToMove duration:2.0
curve:UIViewAnimationCurveLinear x:0.0 y:-200.0];
}
-(void)moveFirstImage:(UIImageView *)image duration: (NSTimeInterval)duration
curve:(int)curve x:(CGFloat)x y:(CGFloat)y{
[UIView animateWithDuration:duration/2 delay:0 options:curve animations:^{
CGAffineTransform transform = CGAffineTransformMakeTranslation(0,y);
image.transform = transform;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:duration/2 delay:0 options:curve animations:^{
CGAffineTransform transform = CGAffineTransformMakeTranslation(-70,-200);
image.transform = transform;
} completion:nil];
}];
}
//Second Image coordinates.
- (void)startAppForSecondImg{
UIImageView *imageToMove =
[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"man.jpg"]];
imageToMove.frame = CGRectMake(20,20,100,100);
[self.view addSubview:imageToMove];
// Move the image
[self moveSecondImage:imageToMove duration:2.0
curve:UIViewAnimationCurveLinear x:0.0 y:290.0];
}
-(void)moveSecondImage:(UIImageView *)image duration: (NSTimeInterval)duration
curve:(int)curve x:(CGFloat)x y:(CGFloat)y{
[UIView animateWithDuration:duration/2 delay:0 options:curve animations:^{
CGAffineTransform transform = CGAffineTransformMakeTranslation(0,y);
image.transform = transform;
}
completion:^(BOOL finished) {
[UIView animateWithDuration:duration/2 delay:0 options:curve animations:^{
CGAffineTransform transform = CGAffineTransformMakeTranslation(90,290);
image.transform = transform;
} completion:nil];
}];
}

How to autorepeat a set of chained UIView animations using UIViewAnimationOptionRepeat

I am trying to chain a set of UIView animateWithDuration: using the flag UIViewAnimationOptionRepeat
The animation steps I am trying to repeat are:
Animate a UIView 100 pixels to the left
Fade the UIView out (opacity '0')
While faded out (invisible), move it back to the original position (100 px to the right)
Fade the UIView back in (set opacity to '1')
Repeat the animation using flag UIViewAnimationOptionRepeat
I am not able to repeat the whole chain of animations - and only able to repeat the top most animation.
The code I have tried is this:
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionRepeat animations:^{
self.handImageView.frame = CGRectMoveByXPixels(self.handImageView.frame, -100);
[UIView animateWithDuration:0.5 delay:1 options:0 animations:^{
self.handImageView.alpha = 0;
} completion:^(BOOL finished) {
self.handImageView.frame = CGRectMoveByXPixels(self.handImageView.frame, 100);
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
self.handImageView.alpha = 1;
} completion:^(BOOL finished) {
}];
}];
} completion:^(BOOL finished) {
}];
The problem is that an animation that uses UIViewAnimationOptionRepeat never finishes and therefore never calls the completion block. However, you can repeat the animations using the performSelector method, as shown in the code below.
- (void)repeatingAnimationForView:(UIView *)view
{
[UIView animateWithDuration:1 delay:0 options:0
animations:^{ view.frame = CGRectMoveByXPixels(view.frame, -100); }
completion:^(BOOL finished) { if ( finished ) {
[UIView animateWithDuration:0.5 delay:0 options:0
animations:^{ view.alpha = 0; }
completion:^(BOOL finished) { if ( finished ) {
view.frame = CGRectMoveByXPixels(view.frame, 100);
[UIView animateWithDuration:0.5 delay:0 options:0
animations:^{ view.alpha = 1; }
completion:^(BOOL finished) { if ( finished ) {
if ( self.enableRepeatingAnimation )
[self performSelector:#selector(repeatingAnimationForView:) withObject:view afterDelay:0];
}}]; }}]; }}];
}
- (void)stopRepeatingAnimationForView:(UIView *)view
{
self.enableRepeatingAnimation = NO;
[view.layer removeAllAnimations];
view.frame = CGRectMake( 100, 137, 80, 50 );
view.alpha = 1;
}
- (void)startRepeatingAnimationForView:(UIView *)view
{
self.enableRepeatingAnimation = YES;
[self repeatingAnimationForView:view];
}
To stop the animations immediately, call the stopRepeatingAnimationForView method as shown above. To stop the animations at the end of a cycle, simply set self.enableRepeatingAnimation to NO.

Animation of UIButton decreases its size

Here is a small clip of a view being animated by me:
Animation flash
I am having problems when animation from ? to S and vice versa. I am setting the appropriate frames to go off screen, and then back on from the other size. Why does the size of the black button decrease with every move around it?
-(void)moveToRight
{
//just made this method up, but my actual code
//special case
if (currentDay == 7) {
//move off the screen to the right
CGRect offScreenRightFrame = CGRectMake(self.circle.frame.origin.x + 60, self.circle.frame.origin.y, self.circle.frame.size.width, self.circle.frame.size.height);
//move to the left of the screen so we can animate it in
CGRect offScreenLeftFrame = CGRectMake(-40, self.circle.frame.origin.y, self.circle.frame.size.width, self.circle.frame.size.height);
if (self.delegate) {
if ([self.delegate respondsToSelector:#selector(dayChangedTo:)]) [self.delegate dayChangedTo:[self getCurrentDay]];
}
[self pulseCircle];
[UIView animateWithDuration:0.25f delay:0.0f options:UIViewAnimationOptionCurveLinear animations:^{
self.circle.frame = offScreenRightFrame;
}completion:^(BOOL finished) {
if (finished) {
self.circle.alpha = 0.0f;
self.circle.frame = offScreenLeftFrame;
[UIView animateWithDuration:0.25f delay:0.0f options:UIViewAnimationOptionCurveLinear animations:^{
self.circle.center = self.labelSun.center;
self.circle.alpha = 1.0f;
}completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:0.25f animations:^{
[self changeColors];
[self pulseCircle];
}];
}
}];
}
}];
}
-(void)moveLeft
{
if (currentDay == 8) {
CGRect circleFrame = self.circle.frame;
CGRect offScreenLeft = CGRectOffset(circleFrame, -20, 0);
CGRect offScreenRightFrame = CGRectMake(self.labelQuestion.frame.origin.x + 30, self.labelQuestion.frame.origin.y, circleFrame.size.width, circleFrame.size.height);
[self pulseCircle];
[UIView animateWithDuration:0.25f delay:0.0f options:UIViewAnimationOptionCurveLinear animations:^{
self.circle.frame = frame;
}completion:^(BOOL finished) {
if (finished) {
self.circle.alpha = 0.0f;
self.circle.frame = frameFinal;
[UIView animateWithDuration:0.25f delay:0.0f options:UIViewAnimationOptionCurveLinear animations:^{
self.circle.center = self.labelQuestion.center;
self.circle.alpha = 1.0f;
}completion:^(BOOL finished) {
if (finished) {
[UIView animateWithDuration:0.25f animations:^{
[self changeColors];
[self pulseCircle];
}];
}
}];
}
}];
}
- (void)pulseCircle
{
__block UILabel *day = [self getLabelOfDay];
[UIView animateWithDuration:TRANLATE_DURATION/2 delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.circle.layer.transform = CATransform3DMakeScale(1.35f, 1.35f, 1);
day.transform = CGAffineTransformMakeScale(1.35f, 1.35f);
}completion:^(BOOL finished) {
[UIView animateWithDuration:TRANLATE_DURATION/2 animations:^{
self.circle.layer.transform = CATransform3DIdentity;
day.transform = CGAffineTransformIdentity;
}];
}];
}
I just put my logic.. honestly i don't read/see your code/logic but may be my idea work for you ;)
So, I think.. you should add size of circle in public variable as default size. And set this size whenever you rich at.
if (currentDay == 0 || currentDay == 8)
{
// Here you need to set your default size.
}
May be my logic work for you, Because 1 to 7 day its work fine but issue created at when currentDay rich at 0 or 8 day.
Thanks :)

When creating an animation to cause a UIImageView to go up and down (almost float) infinitely, how do I stop a pause at the end of the animation?

Here's the code I'm using to take a UIImageView and make it float up and down.
[UIView animateKeyframesWithDuration:2.0 delay:0.0 options:UIViewKeyframeAnimationOptionRepeat animations:^{
[UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:0.25 animations:^{
self.slider.transform = CGAffineTransformMakeTranslation(0, -5.0);
}];
[UIView addKeyframeWithRelativeStartTime:0.25 relativeDuration:0.5 animations:^{
self.slider.transform = CGAffineTransformMakeTranslation(0, 5.0);
}];
[UIView addKeyframeWithRelativeStartTime:0.75 relativeDuration:0.25 animations:^{
self.slider.transform = CGAffineTransformMakeTranslation(0, 0.0);
}];
} completion:^(BOOL finished) {
}];
However, it comes out looking like this with this delay after the animation ends and before it restarts.
How do I make it fluid?
I'm not sure what effect you're going for exactly, but I think this gives you something like your code does without the delay. I usually do this by animating a constraint, rather than using transforms. In this example, I've made an IBOutlet (topCon) to the constraint to the top of the view:
-(IBAction)floatView:(id)sender {
static int i= 1;
static float duration = .25;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.topCon.constant = self.topCon.constant - (5 * i);
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
i = (i == 1 || i == 2)? -2 : 2;
duration = 0.5;
[self floatView:self];
}];
}

Resources