When this method is first called, it works good.
On second call, the delay does not work.
The other code works good except for the delay.
How do I solve this problem?
-(void)makeParticle:(id)sender{
Bubble *bubble=(Bubble*)sender;
CGPoint center=bubble.center;
NSInteger radian=arc4random()%360;
for (int i=1; i<=13; i++) {
NSInteger distance=20+arc4random()%80;
radian+=10+arc4random()%40;
UIImageView *iv=[[[UIImageView alloc]initWithImage:[UIImage imageNamed:[NSString stringWithFormat:#"star%i.png",i]]]autorelease];
NSInteger size=20+arc4random()%20;
iv.frame=CGRectMake(0, 0, size, size);
iv.center=center;
iv.alpha=0;
[self addSubview:iv];
[iv release];
[UIView animateWithDuration:0.4 delay:0.1 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction animations:^(void) {
iv.alpha=0.5;
iv.center=CGPointMake(center.x+distance*cos(radian), center.y+distance*sin(radian));
} completion:^(BOOL finished) {
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction animations:^(void) {
iv.center=CGPointMake(600, 100);
iv.alpha=0;
} completion:^(BOOL finished) {
[iv removeFromSuperview];
}];
}];
}
}
Related
I'm having some issues with my animations. The intended result is that the UIButton's should both move to their positions, and once they reach their positions they must oscillate upwards and downwards, subtly, to simulate reaching the end of their bungee chord, if you will. The result I'm achieving is that every animation apart from the oscillation is executing perfectly. Why is this? (The oscillation animation I refer to is, of course, the spring animateWithDuration method.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
_orText.alpha = 0;
//Email login button properties
_emailLoginForwardButton.layer.cornerRadius = _emailLoginForwardButton.frame.size.width / 2;
self.emailLoginForwardButton.layer.borderWidth = 1.5f;
self.emailLoginForwardButton.layer.borderColor = [UIColor whiteColor].CGColor;
[self.emailLoginForwardButton setImageEdgeInsets:UIEdgeInsetsMake(7, 7, 7, 7)];
_emailLoginForwardButton.frame = CGRectMake(77, 700, 40, 40);
[UIView animateWithDuration:0.5
animations:^
{
_emailLoginForwardButton.frame = CGRectMake(77, 470, 40, 40);
}
completion:^(BOOL finished)
{
[UIView animateWithDuration:0.3
delay:0.6
usingSpringWithDamping:0.2
initialSpringVelocity:0.4
options:0
animations:^(void){}
completion:^(BOOL finished)
{
_orText.text = #"or";
[UIView animateWithDuration:0.4
animations:^
{
[_orText setAlpha:1];
}
];
}
];
}
];
//Google login button properties
_googleLoginForwardButton.layer.cornerRadius =_googleLoginForwardButton.frame.size.width / 2;
self.googleLoginForwardButton.layer.borderWidth = 1.5f;
self.googleLoginForwardButton.layer.borderColor = [UIColor grayColor].CGColor;
_googleLoginForwardButton.frame = CGRectMake(257, 700, 40, 40);
[UIView animateWithDuration:0.5
delay:0.4
options:0
animations:^
{
_googleLoginForwardButton.frame = CGRectMake(257, 470, 40, 40);
}
completion:^(BOOL finished)
{
[UIView animateWithDuration:0.3
delay:0.3
usingSpringWithDamping:0.2
initialSpringVelocity:0.4
options:0
animations:^
{
}
completion:^(BOOL finished)
{
}
];
}
];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.googleLoginForwardButtonBottomConstraints.constant = -100.0;//e.g
self.emailLoginForwardButtonBottomConstraints.constant = -100.0;//e.g
[UIView animateWithDuration:0.6
delay:0.6
usingSpringWithDamping:0.2
initialSpringVelocity:0.4
options:0
animations:^(void){
self.googleLoginForwardButtonBottomConstraints.constant = 40.0;//e.g
self.emailLoginForwardButtonBottomConstraints.constant = 40.0;//e.g
[self.view layoutIfNeeded];
}
completion:^(BOOL finished) {
}];
}
I have run this code and its working. Hope it will help you.
[UIView animateWithDuration:1
delay:0.6
usingSpringWithDamping:0.42
initialSpringVelocity:0.1
options:0
animations:^(void)
{
_orText.text = #"or";
[UIView animateWithDuration:0.7
animations:^
{
[_orText setAlpha:1];
}];
[UIView animateWithDuration:0.6
animations:^
{
_emailLoginForwardButton.frame = CGRectMake(77, 470, 40, 40);
}];
[UIView animateWithDuration:0.6
animations:^
{
_googleLoginForwardButton.frame = CGRectMake(257, 470, 40, 40);
}
];
[self.view layoutIfNeeded];
}
completion:^(BOOL finished) {
}];
This was my solution, however there was more I wanted to do with this code. I wanted to make both buttons move at different intervals, and an if statement won't work here, for some reason. Also, I only wanted this to initialise when another action has taken place, which is still possible to do, but I'd prefer to be able to make them move at different times.
I have this simple animation that fades in several labels, one at a time. But I wonder if it is possible to reduce the code with this logic?
[UIView animateWithDuration:0.50f animations:^{
[_latLabel setAlpha:0.9f];
[_firstLat setAlpha:0.9f];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.50f animations:^{
[_lonLabel setAlpha:0.9f];
[_firstLon setAlpha:0.9f];
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.50f animations:^{
[_speedLabel setAlpha:0.9f];
[_firstSpeed setAlpha:0.9f];
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.50f animations:^{
[_realNorthLabel setAlpha:0.9f];
[_firstReal setAlpha:0.9f];
}completion:^(BOOL finished) {
[UIView animateWithDuration:0.50f animations:^{
[_magneticNorthLabel setAlpha:0.9f];
[_firstMagnetic setAlpha:0.9f];
}];
}];
}];
}];
}];
Considering the need to perform operation on 2 label objects while executing any single section of the animation block, create a dictionary structure wherein section indexes define the chronological order of the sections animations to be performed & each section index contains an array of label objects.
A simple iterating loop over this structure christened here as dictionaryOfSectionedLabels can help achieve the desired alternate animation implementation.
NSDictionary<NSNumber *, NSArray *> *dictionaryOfSectionedLabels = #{ #0: #[_latLabel, _firstLat],
#1: #[_lonLabel, _firstLon],
#2: #[_speedLabel, _firstSpeed],
#3: #[_realNorthLabel, _firstReal],
#4: #[_magneticNorthLabel, _firstMagnetic]
};
for (NSUInteger i = 0; i < dictionaryOfSectionedLabels.allKeys.count; i++) {
[UIView animateWithDuration:0.5 delay:0.5*i options:UIViewAnimationOptionLayoutSubviews animations:^{
UILabel *firstLabel = [dictionaryOfSectionedLabels[#(i)] firstObject];
UILabel *secondLabel = [dictionaryOfSectionedLabels[#(i)] lastObject];
firstLabel.alpha = 0.9f;
secondLabel.alpha = 0.9f;
} completion:nil];
}
Creating an NSDictionary of your labels can be tedious and confusing code to read in the future. I'd recommend you just create a method.
-(void)customFadeForLabel:(UILabel *)theLabel withDelay:(float)delayAmount {
[UIView animateWithDuration:0.50f
delay:delayAmount
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[theLabel setAlpha:0.9f];
}completion:nil];
}
Then just call it as needed with delays
[self customFadeForLabel:_latLabel withDelay:0.00f];
[self customFadeForLabel:_firstLat withDelay:0.00f];
[self customFadeForLabel:_lonLabel withDelay:0.50f];
[self customFadeForLabel:_firstLon withDelay:0.50f];
[self customFadeForLabel:_speedLabel withDelay:1.00f];
[self customFadeForLabel:_firstSpeed withDelay:1.00f];
[self customFadeForLabel:_realNorthLabel withDelay:1.50f];
[self customFadeForLabel:_firstReal withDelay:1.50f];
[self customFadeForLabel:_magneticNorthLabel withDelay:2.00f];
[self customFadeForLabel:_firstMagnetic withDelay:2.00f];
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.
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];
}];
I'm having a bit of trouble. I've set my UIView Animation to repeat itself infinitely, however it does this before the animation starts it's completion function. I want it to wait until after the completion function fully runs because I want to run multiple animations. Any idea how to do this? If not is there a different way I can accomplish the same thing?
I'll post my code below:
-(void) createBlueControlAnimation:(int)messageCount{
if(messageCount == 0) {
return;
}
[blueControl setContentOffset:CGPointMake(0, 0)];
[UIView animateWithDuration:0.5 delay:2 options:UIViewAnimationOptionRepeat
animations:^{
[blueControl setContentOffset:CGPointMake(screenWidth, 0)];
} completion:^(BOOL finished){
if(messageCount >= 2){
[UIView animateWithDuration:0.5 delay:2 options:UIViewAnimationOptionAllowAnimatedContent
animations:^{
[blueControl setContentOffset:CGPointMake(screenWidth * 2, 0)];
} completion:^(BOOL finished){
if(messageCount == 3) {
[UIView animateWithDuration:0.5 delay:2 options:UIViewAnimationOptionAllowAnimatedContent
animations:^{
[blueControl setContentOffset:CGPointMake(screenWidth * 3, 0)];
}completion:^(BOOL finished){
[self scrollAnimationToStart];
}];
}else{
[self scrollAnimationToStart];
}
}];
}else{
[self scrollAnimationToStart];
}
}];
}
-(void) scrollAnimationToStart {
[UIView animateWithDuration:0.5 delay:2 options:UIViewAnimationOptionAllowAnimatedContent
animations:^{
[blueControl setContentOffset:CGPointMake(0, 0)];
} completion:^(BOOL finished){}];
}
So based on the number of messages I want the animation to continue running, and then when it gets to the last message, loop back to the first message and then restart the animation. However right now it just loops infinitely between the first and the second message. Any ideas on how to fix this would be greatly appreciated, thanks.
Firstly: You should create separate consts for anything that is in code.
extern NSTimeInterval const animationDuration;
NSTimeInterval const animationDuration = 0.5;
extern NSTimeInterval const animationDelay;
NSTimeInterval const animationDelay = 2;
Secondly: intent your code in reasonable way, it's quite hard to read what you've pasted. Use one method and push every repeatable part of code into another method.
- (void)createBlueControlAnimation:(NSUInteger)messageCount {
if (messageCount == 0) {
return;
}
__weak typeof(self) weakSelf = self;
[self offsetBlueControl:0];
[UIView animateWithDuration:animationDuration delay:animationDelay options:UIViewAnimationOptionAllowAnimatedContent animations:^{
[weakSelf offsetBlueControl:screenWidth];
} completion:^(BOOL finished) {
if (messageCount < 2) {
[self scrollAnimationToStart];
} else {
[UIView animateWithDuration:animationDuration delay:animationDelay options:UIViewAnimationOptionAllowAnimatedContent animations:^{
[weakSelf offsetBlueControl:screenWidth * 2];
} completion:^(BOOL finished) {
if (messageCount != 3) {
[self scrollAnimationToStart];
} else {
[UIView animateWithDuration:animationDuration delay:animationDelay options:UIViewAnimationOptionAllowAnimatedContent animations:^{
[weakSelf offsetBlueControl:screenWidth * 3];
} completion:^(BOOL finished) {
[self scrollAnimationToStart];
}];
}
}];
}
}];
}
- (void)scrollAnimationToStart {
[UIView animateWithDuration:animationDuration delay:animationDelay options:UIViewAnimationOptionAllowAnimatedContent animations:^{
[blueControl setContentOffset:CGPointMake(0, 0)];
} completion:^(BOOL finished) {}];
}
- (void)offsetBlueControl:(CGFloat)xOffset {
[blueControl setContentOffset:CGPointMake(xOffset, 0)];
}
I should mention here that this animation block is in fact similar everywhere. I'd set it as a separate method also.
Thirdly, keep same way of spacing everywhere (eg check out https://github.com/NYTimes/objective-c-style-guide).
That's all about code, the quality, readibility etc. I'd set it as comment, but there's too much code in my response, so it has to be an answer.
I don't fully understand what do you want to do. As far as I understood:
You have a UI element, called BlueControl.
You want to move this element.
Basing on some counter you want to move your view by some width (btw I advise to switch to NSIntegers from ints and use unsigned option, so NSUInteger etc). The move steps:
3.1. Move button right during 0.5s
3.2. Wait 2 seconds if counter is large enough, otherwise end step 3
3.3. Increase counter, repeat step 3.
You want to repeat the process infinitely.
Is that right? I need to understand the problem to edit this answer and paste a full response here.