I am working on a kids app and need to make the answer disappear after a few seconds.
What do I need to add?
- (IBAction)calculate2:(id)sender
{
float aaaa = 6;
Answer2.text = [ [NSString alloc] initWithFormat:#"%.0f ",aaaa];
}
Use NSTimer and mention the specified time for UILabel to disappear:
- (IBAction)calculate2:(id)sender
{
float aaaa = 6;
Answer2.text = [[NSString alloc] initWithFormat:#"%.0f ",aaaa];
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(targetMethod:)
userInfo:nil
repeats:NO];
}
-(void)targetMethod:(NSTimer*)timer
{
//toggle hidden parameter
[Answer2 setHidden:!Answer2.hidden];
}
-(void) hideLabel
{
[Answer2 setHidden:YES];
}
just add [self performSelector:#selector(hideLabel) withObject:nil afterDelay:4] to calculate2
For hiding it non-animated it will be:
[label setHidden:YES];
But if you want to hide it with an Animation it could be:
[UIView animatedwithduration:1.0f delay:.35f animations:{
label.alpha = 0.0;
}completion:{
[label removeFromSuperview];
//Here you can put a completed code
}];
Hope it helps!
Related
I am trying to implement method that affect UILabel text each every 1 seconds , It is going to be a reminder text like " You can skip ad in 5,4,3,2,1 skip now >>"
My method works fine except in 2nd and 3rd seconds timer call method like a more than 1 times each on second. I am using UIApplication sharedapplication.keywindows for present UI over full screen MPMoviePlayerController . Here is my method :
-(void)closeButtonForVideoPlayer
{
myButton = [[UIButton alloc] initWithFrame:CGRectMake(self.view.frame.size.width-30, 12, 25, 25)];
window = [UIApplication sharedApplication].keyWindow;
if (!window)
{
window = [[UIApplication sharedApplication].windows objectAtIndex:0];
}
[myButton addTarget:self action:#selector(videoFinished:) forControlEvents:UIControlEventTouchUpInside];
[myButton setImage:self.closeButton forState:UIControlStateNormal];
labelReminder = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.size.width-130, 12, 130, 35)];
labelReminder.textColor = [UIColor whiteColor];
labelReminder.backgroundColor = [UIColor blackColor];
self.timderReminder = [NSTimer scheduledTimerWithTimeInterval:1.0
target: self
selector:#selector(reminderForVideoPlayer:)
userInfo: #{#"boolType":#"YES"} repeats:NO];
}
The reminder method :
-(void)reminderForVideoPlayer:(NSTimer *)userInfo
{
NSString *isVideoAdvertisement = [userInfo.userInfo objectForKey:#"boolType"];
NSLog(#"NSTimer info = %#",userInfo.userInfo);
if([isVideoAdvertisement isEqualToString:#"YES"])
{
if(remind >= 5)
{
[self.timderReminder invalidate];
remind = 0;
NSLog(#"reklam geçildi window");
[labelReminder removeFromSuperview];
labelReminder = nil;
[labelReminder setHidden:YES];
[window addSubview:myButton];
} else {
[window addSubview:labelReminder];
[labelReminder setText:[NSString stringWithFormat:#"Reklami geç: %d",5-remind]];
NSLog(#"reminder window = %d",remind);
remind ++;
self.timderReminder = [NSTimer scheduledTimerWithTimeInterval:1.0
target: self
selector:#selector(reminderForVideoPlayer:)
userInfo: #{#"boolType":#"YES"} repeats:NO];
}
}
Which part i am making mistake ? and how i can fix that issue ?
Best Regards,
Onder OZCAN
Try this control it will fulfil your requirements
https://github.com/mineschan/MZTimerLabel
in viewDidLoad
self.timderReminder = [NSTimer scheduledTimerWithTimeInterval:1.0
target: self
selector:#selector(reminderForVideoPlayer:)
userInfo: #{#"boolType":#"YES"} repeats:YES];
and
-(void)reminderForVideoPlayer:(NSTimer *)userInfo
{
NSString *isVideoAdvertisement = [userInfo.userInfo objectForKey:#"boolType"];
NSLog(#"NSTimer info = %#",userInfo.userInfo);
if([isVideoAdvertisement isEqualToString:#"YES"])
{
if(remind < 5)
{
[labelReminder setText:[NSString stringWithFormat:#"Reklami geç: %d",5-remind]];
NSLog(#"reminder window = %d",remind);
[labelReminder setHidden:NO];
} else {
[labelReminder setHidden:YES];
// [window addSubview:myButton]; //add this button in view did load only over here use setHidden method
[myButton setHidden: NO];
}
}
Try with this code.
Change the repeats parameter of NSTimer to YES. And you won't have to create a timer again each time it's fired. When your counter reaches to 5, just invalidate your timer.
I am trying to get a button to move to random locations inside my view. However, the dot only moves at random when it is pressed. I also want it to fade to a different location if it is not pressed. I used CGRect because I need the dot to stay within the bounds of a specific view.
-(IBAction)randomRed:(id)sender
{
[self redDot];
CGRect senderFrame = [sender frame];
CGRect superBounds = [[sender superview ] bounds];
senderFrame.origin.x = (superBounds.size.width - senderFrame.size.width) * drand48();
senderFrame.origin.y = (superBounds.size.height - senderFrame.size.height) * drand48();
[sender setFrame:senderFrame];
counter = counter - 5;
scoreLabel.text = [NSString stringWithFormat:#"Points %i", counter];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Tapadot Red Dot Buzzer Short" ofType:#"mp3"];
sound = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
sound.numberOfLoops = 1;
[sound play];
[self subtractOne];
[self performSelector:#selector(showRedDot) withObject:nil afterDelay:1.0];
}
-(void)startRedDot
{
if (counter ==0)
redDot = [NSTimer scheduledTimerWithTimeInterval:4.0
target:self
selector:#selector(showRedDot)
userInfo:nil
repeats:YES];
}
-(void)showRedDot
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[redButton setAlpha:1];
[UIView commitAnimations];
[self performSelector:#selector(redDot) withObject:nil afterDelay:1.0];
}
-(void)redDot
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[redButton setAlpha:0];
[UIView commitAnimations];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setUpGame];
[self sizing];
}
Currently your random positioning code is only called when the button is pressed.
To get it to move Independent of button presses we should put it in its own method, which can invoke itself after a set duration.
First we need to get a reference to the instance of the button you want to move so we can manipulate it.
Then lets separate the movement code into its own method.
- (void) moveButtonRandomly {
CGSize limits;
CGPoint newPosition;
// Get limits
limits.width = self.view.frame.size.width - button.frame.size.width;
limits.height = self.view.frame.size.height - button.frame.size.height;
// Calculate new Position
newPosition = (CGPoint){ limits.width * drand48(), limits.height * drand48() };
// Set new frame
button.frame = (CGRect){ newPosition, button.frame.size };
}
Change your startRedDot to this, which will construct, and start the timer.
- (void) startRedDot {
redDotTimer = [NSTimer scheduledTimerWithTimeInterval:4.0
target:self
selector:#selector(moveButtonRandomly)
userInfo:nil
repeats:YES];
[redDotTimer fire];
}
The animation is rather simple to add just create a new method which invokes two animations; One which fades out the button with a completion that moves the button, and fires off the next animation to fade it back in.
- (void) moveButtonWithAnimation {
CGFloat fadeDurration;
if ( !button )
return; // only invoke the button if it exists
fadeDurration = 0.4;
//Fade Out
[UIView animateWithDuration: fadeDurration animations:^{
button.alpha = 0.0f;
} completion:^(BOOL finished) {
// Move the button while it is not visible
[self moveButtonRandomly];
// Fade in
[UIView animateWithDuration: fadeDurration animations:^{
button.alpha = 1.0f;
}];
}];
}
Finally Edit the timers selector to be the animation method.
- (void) startRedDot {
redDotTimer = [NSTimer scheduledTimerWithTimeInterval:4.0
target:self
selector:#selector(moveButtonWithAnimation)
userInfo:nil
repeats:YES];
[redDotTimer fire];
}
I am using NSTimer and circular progress bar for the countdown timer i.e 15seconds
Its working with the following code but I am getting tick animation for the progress bar and not the smooth one, how to make it smooth animation
- (void)viewDidLoad
{
[super viewDidLoad];
self.labeledLargeProgressView.roundedCorners = NO;
self.labeledLargeProgressView.trackTintColor =[UIColor colorWithRed:0.0f/255.0f green:173.0f/255.0f blue:255.0f/255.0f alpha:1.0f];
self.labeledLargeProgressView.progressTintColor =[UIColor colorWithRed:255.0f/255.0f green:96.0f/255.0f blue:88.0f/255.0f alpha:1.0f];
self.labeledLargeProgressView.thicknessRatio = 1.0f;
self.labeledLargeProgressView.clockwiseProgress = YES;
[self.view addSubview:self.labeledLargeProgressView];
seconds = 15.0;
[self startAnimation];
}
- (void)progressChange
{
CGFloat progress ;
DALabeledCircularProgressView *labeledProgressView = self.labeledLargeProgressView;
if(labeledProgressView.progress >=1.0f && [self.timer isValid]){
[self stopAnimation];
seconds = 15.0f;
}
else{
progress=labeledProgressView.progress + 0.06666667f;
[labeledProgressView setProgress:progress animated:YES];
seconds --;
labeledProgressView.progressLabel.text = [NSString stringWithFormat:#"%i", seconds];
}
}
- (void)startAnimation
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
self.continuousSwitch.on = YES;
}
- (void)stopAnimation
{
[self.timer invalidate];
self.timer = nil;
self.continuousSwitch.on = NO;
}
What i found out is a set of both UIview animations and progress view animatons that work much nicer and animate the progressview smoothly. If you just use the combination of animation and progressview animation it is fired directly without regard to the UIview animation timer.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0f
target: self
selector: #selector(updateTimer)
userInfo: nil
repeats: YES];
}
- (void)updateTimer
{
if (progressView.progress >= 1.0) {
[timer invalidate];
}
[UIView animateWithDuration:1 animations:^{
float newProgress = [self.progressView progress] + 0.125;
[self.progressView setProgress:newProgress animated:YES];
}];
}
Feel free to adjust the animation times to even better and smooth transitions
I solved it by myself what I did is I am updating more frequently 0.1f instead of 1.0f
- (void)progressChange
{
CGFloat progress ;
DALabeledCircularProgressView *labeledProgressView = self.labeledLargeProgressView;
if(labeledProgressView.progress >=1.0f && [self.timer isValid]){
[self stopAnimation];
seconds = 15.0f;
_counter = 0;
}
else{
progress=labeledProgressView.progress + 0.00666667f;
_counter ++;
[labeledProgressView setProgress:progress animated:YES];
if(_counter % 10 == 0){
seconds --;
}
labeledProgressView.progressLabel.text = [NSString stringWithFormat:#"%i", seconds];
}
}
- (void)startAnimation
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(progressChange)
userInfo:nil
repeats:YES];
self.continuousSwitch.on = YES;
}
So here's my code :
- (IBAction)run:(id)sender {
animationPointer = 0;
self.animationArray = [[NSMutableArray alloc] init];
UIView *allViews = [[UIView alloc]
initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
for (int i = 0; i < [self.paths count]; i++) {
[allViews addSubview:[self createAnimation:[self.paths objectAtIndex:i]]];
[self.animationArray addObject:allViews];
}
timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(animateTurn)
userInfo:nil repeats:YES];
}
- (void)animateTurn {
UIView *tempView = [self.animationArray objectAtIndex:animationPointer];
[self.view addSubview:tempView];
for (UIImageView *view in tempView.subviews) {
[[tempView.subviews objectAtIndex:animationPointer] startAnimating];
}
animationPointer++;
if (animationPointer >= [self.animationArray count]) {
[timer invalidate];
}
}
createAnimation returns, as you would expect, a fully animated UIImageView. The plan is to have several on each UIView and then animate them all on a UIView then the next after half a second and it repeats. There's only one on each UIView for now.
However, when calling animateTurn on the NSTimer, the animations don't show up.
If I call the method via the normal [self animateTurn] then they appear but nothing with NSTimer nor the performSelector function.
Any help with this (or even suggestions for a better method)?
EDIT:
I should mention the function is actually being triggered and the code is being run including the startAnimating (checked with BOOL/NSLog). There is simply nothing being shown.
This is Your Solution:-
This is what I used and now the selector is Working. :-)
if (![NSThread isMainThread])
{ [self performSelectorOnMainThread:#selector(selectorToRunInMainThread) withObject:nil waitUntilDone:NO];
}
-(void)selectorToRunInMainThread
{
NSString *str = #"Timer event has fired";
NSTimer *atimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateModel:) userInfo:str repeats:YES];
}
Include this line after your timer:-
[timer fire];
I have an animation that is not animating for some reason.
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBar.hidden = YES;
self.nameLabel.text = [self.name uppercaseString];
self.gradient1.alpha = .9;
self.gradient1.image = [UIImage imageNamed:#"heart.png"];
self.gradient1.animationImages = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"gradiant1.png"],
[UIImage imageNamed:#"gradiant2.png"],
...
[UIImage imageNamed:#"gradiant26.png"], nil];
self.gradient1.animationDuration = .5;
self.gradient1.animationRepeatCount = 1;
[self updateStats:nil];
}
-(void)updateStats:(NSTimer*)timer{
Utilities *utility = [[Utilities alloc] init];
[utility getDataWithSSID:self.ssID completion:^(bool *finished, NSArray *objects) {
if (finished){
...
[self.gradient1 startAnimating];
}
self.twoSecTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self
selector:#selector(updateStats:)
userInfo:nil
repeats:NO];
}];
}
Sometimes it animates once or twice and then stops even though the timer continues to hit over and over. Other times it just doesn't animate at all. However, I have a couple placeholder buttons that I put on the storyboard that aren't tied to anything and whenever I press one of the buttons it animates the next time the timer hits (Actually whenever I hit the screen even though I don't have any sort of gesture recognizers..). Also, when I add in all the other garbage I want to do in this ViewController it animates every other time it's being called. So I think it's something deeper than me forgetting so set some property.
It might be a better idea to move the animation trigger to a moment when that view is actually visible - hence to viewDidAppear:.
Also your way of creating a recursive timer scheduling makes me shiver. I guess it works fine for you but I would definitely suggest to use the repeats flag set to YES instead.
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBar.hidden = YES;
self.nameLabel.text = [self.name uppercaseString];
self.gradient1.alpha = .9;
self.gradient1.image = [UIImage imageNamed:#"heart.png"];
self.gradient1.animationImages = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"gradiant1.png"],
[UIImage imageNamed:#"gradiant2.png"],
...
[UIImage imageNamed:#"gradiant26.png"], nil];
self.gradient1.animationDuration = .5;
self.gradient1.animationRepeatCount = 1;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
//animate right away...
[self updateStats:nil];
//trigger new animations every two seconds
self.twoSecTimer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self
selector:#selector(updateStats:)
userInfo:nil
repeats:YES];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self stopUpdatingStats];
}
-(void)stopUpdatingStats
{
[self.twoSecTimer invalidate];
}
-(void)updateStats:(NSTimer*)timer
{
NSLog(#"updating");
[self.gradient1 startAnimating];
}