I have a UISlider and I am trying to add subviews dynamically on the track of the UISlider with animation. I need 1 second time delay before adding each subview. How can I achieve this?
This is a basic setup of how you can go about achieving it:
#interface ViewController () {
NSTimer *_timer;
CGRect sliderFrame;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.slider.minimumValue = 0.0f;
self.slider.maximumValue = 100.0f;
sliderFrame = self.slider.frame;
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(addLabel:) userInfo:nil repeats:YES];
[_timer fire];
}
- (void) addLabel:(NSTimer*) timer {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(sliderFrame.origin.x + self.slider.value/100 * self.slider.frame.size.width, sliderFrame.origin.y - 10, 20, 20)];
label.text = #"1";
[self.view addSubview:label];
}
#end
Assuming you are using an animation block, then, within your block you can use setAnimationDelay. For example;
[UIView animateWithDuration:5.0 animations:
^{
[UIView setAnimationDelay:1.0];
...
} completion:^(BOOL finished){
...
}];
This would do a 5 second animation with a delay of 1 second before it started.
you can hook up the valueChangeEvent with an action method.
You can put an animation block in that method with passing the seconds to wait before starting an animation as delay parameter.
[UIView animateWithDuration:(NSTimeInterval) delay:(NSTimeInterval) options:(UIViewAnimationOptions) animations:^(void)animations completion:^(BOOL finished)completion]
then you can change add the view with whatever animation your require.
Related
I have been trying to make my UILabel blink in Xcode
but the problem is it does not blink
Here is my code:
self.labelCountdownTime.alpha = 0.0;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatCount:FLT_MAX];
self.labelCountdownTime.alpha = 1.0;
[UIView commitAnimations];
Is there something I'm doing wrong.
Thanks
You can use NSTimer to blink your text in UILabel like so:
NSTimer *timer = [NSTimer
scheduledTimerWithTimeInterval:(NSTimeInterval)(1.0)
target:self
selector:#selector(blink)
userInfo:nil
repeats:YES];
BOOL blinkStatus = NO;
And the selector will call this function:
-(void)blink{
if(blinkStatus == NO){
yourLabel.alpha = 1.0;
blinkStatus = YES;
}else {
yourLabel.alpha = 0.0;
blinkStatus = NO;
}
}
Or you can use method animationWithDuration of UIView like so:
self.yourLabel.alpha = 0;
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse animations:^{
self.yourLabel.alpha = 1;
} completion:nil];
Hope this will help you.
I Think you are wanting some thing more like the following:
Create a timer in your controller:
#property (strong, nonatomic) NSTimer *timer;
then start the timer where you need it to start, like maybe in viewDidLoad
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(toggleLabelAlpha) userInfo:nil repeats:YES];
and here is the selector:
- (void)toggleLabelAlpha {
[self.labelCountdownTime setHidden:(!self.labelCountdownTime.hidden)];
}
Try this ?
I implemented corePlot in my xcode project. I'm trying to "explode" a slice of the pie chart with animation. Here is the method I'm using:
- (void)radialOffsetForPieChart:(CPTPieChart *)pieChart recordIndex:(NSUInteger)idx
{
if (myIndex == idx) {
return 20;
}
return 0;
}
I have another method which calls [pieChart reloadRadialOffset];.
For example:
- (void)thisMethod {
[pieChart reloadRadialOffset];
}
How can I animate the reloadRadialOffsets?
I just added an example to the "Simple Pie Chart" demo in the Plot Gallery example app. I added two properties to the controller to hold the index of the selected slice and the desired offset value. Since the offset is a CGFloat it is easily animated using Core Animation or CPTAnimation.
Set the index to NSNotFound to indicate that no slice should be selected. You could also use an array or set of indices if you want to highlight more than one slice at a time.
self.offsetIndex = NSNotFound;
Trigger the animation to offset the slice:
self.offsetIndex = idx;
[CPTAnimation animate:self
property:#"sliceOffset"
from:0.0
to:35.0
duration:0.5
animationCurve:CPTAnimationCurveCubicOut
delegate:nil];
The plot datasource needs the radial offset method:
-(CGFloat)radialOffsetForPieChart:(CPTPieChart *)pieChart recordIndex:(NSUInteger)index
{
return index == self.offsetIndex ? self.sliceOffset : 0.0;
}
The sliceOffset property needs a custom setter to trigger the plot to update the offsets during the animation:
-(void)setSliceOffset:(CGFloat)newOffset
{
if ( newOffset != sliceOffset ) {
sliceOffset = newOffset;
[self.graphs[0] reloadData];
}
}
In your question is bit confusing. Your question title says "how to reaptedly call a mathod using timer" and at the end of your question it changes to "How can I animate the reloadRadialOffsets?".
For repeatedly calling a method you can use any of the following options
option 1.
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(animatedPie:)
userInfo:nil
repeats:YES];
option 2:
[self performSelector:#seletor(animatePie) withObject:nil afterDelay:1.0];
and in your method
-(void) animatePie
{
[UIView animateWithDuration:1.0 animations:^
{
[pieChart reloadRadialOffsets];
} completion:^(BOOL finished)
{
[self performSelector:#seletor(animatePie) withObject:nil afterDelay:1.0];
}];
}
Here the repeated method will be called agian with a delay once the animation is complete.
When you wanted to stop the animation call
- (void)cancelPerformSelector:(SEL)aSelector target:(id)target argument:(id)arg
When timer is used it will be fired once the interval is elapsed.
For animation
You can use
[UIView animateWithDuration:1.0 animations:^
{
} completion:^(BOOL finished) {
}];
or user
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key];
You can use below code. In this UIViewAnimationOptionRepeat is helpful for repeat animation what you want to achieve..
[UIView animateWithDuration:5
delay:1
options:UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionRepeat
animations:^{
[UIView setAnimationRepeatCount:2];
[pieChart reloadRadialOffsets];
}
completion:nil];
//Still you want to call method using timer
NSTimer *animateTimer;
animateTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self
selector:#selector(thisMethod) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:animateTimer forMode:NSDefaultRunLoopMode];
[animateTimer fire];
- (void)thisMethod {
[pieChart reloadRadialOffsets];
}
Hope it helps you...!
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 stuck in something I hope you guys can help
I have a scrollview , when the user scrolling a subview appear with animation from bottom to top. the timer then start counting 5 sec and then call another method to hide the subview
I implemented and it works as wanted except :
while the subview appear and when it's almost to hide , if I scrolled that moment the subview appear statically and never hide . try to scrolling again another subview dynamically work over the static one ( as it duplicated or something)
this is my code for controlling show and hide of subview
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if(!show){
[self showSubview];
if (!myidleTimer)
[self resetIdleTimer];
}
}
-(void)resetIdleTimer
{
//convert the wait period into minutes rather than seconds
int timeout = kApplicationTimeoutInMinutes;// equal to 5 seconds
[myidleTimer invalidate];
myidleTimer = [NSTimer scheduledTimerWithTimeInterval:timeout target:self selector:#selector(idleTimerExceeded) userInfo:nil repeats:NO];
}
-(void)idleTimerExceeded
{
if (show){
[myidleTimer invalidate];
[self hideSubview];
show=false;
}
}
"show" is a bool to insure when to hide and when to show
her is the show / hide implementation
-(void)hideSubview{
[UIView animateWithDuration:0.5
animations:^{
subview.frame = CGRectMake(0, screenWidth, screenHeight, 60);//move it out of screen
} completion:^(BOOL finished) {
[subview removeFromSuperview];
subview.frame=CGRectMake(0,screenWidth, screenHeight, 0);
}];
show=false;
}
-(void) showSubview{
subview = [[UIView alloc] init ];
[self.view addSubview:subview];
subview.frame = CGRectMake(0, screenWidth, screenHeight, 60);
[UIView animateWithDuration:1.0
animations:^{
subview.frame = CGRectMake(0, screenWidth-60, screenHeight, 60);
}];
show=TRUE;
}
I hope that's clear enough to understand and be able to help me identify the problem
thanks in advance
The timer will not fire while the scroll view is being scrolled, if you create the timer the way you do. Instead, create it as below.
NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:#selector(doStuff:) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
scheduledTimerWithTimeInterval:target:selector:userInfo:repeats: adds the timer to the run loop using the defaultRunLoopMode instead of the NSRunLoopCommonModes, which is the one you want to have timer fire while the user scrolls.
I have a UIView in that, I am going to add 15 UIButtons. If I have written code like this
for(int i =0; i<15;i++)
{
[self.view addSubview:[self.buttonsArray objectAtIndex;i]];
}
But I want to subview UIButtons one after other. something like animation effect.How to achieve it.
try this:
in .h file
NSTimer *timer;
int buttonNo;
#property (nonatomic,retain) NSTimer *timer;
in .m file
#synthesize timer;
-(void) viewDidLoad {
[super viewDidLoad];
//start your timer where you write your for loop
buttonNo = 0;
timer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:#selector(addbuttons) userInfo:nil repeats:YES];
}
-(void) addbuttons {
[self.view addSubview:[self.buttonsArray objectAtIndex;buttonNo]];
buttonNo++;
if (buttonNo == 15) {
[timer invalidate];
timer = nil;
}
}
I would do it like this:
const float fadein_duration = 0.3f;
const float time_between_fadein = 0.15f;
int index = 0;
for (UIButton* button in self.buttonsArray)
{
[self.view addSubview:button];
button.alpha = 0.0f;
[UIView animateWithDuration:fadein_duration delay:(index * time_between_fadein) options:0 animations:^{
button.alpha = 1.0f;
} completion:^(BOOL finished) {
// Do something maybe?
}];
index++;
}
Currently, the animation is to fade-in, but you should be able to adapt it to other types of animations.
There are 2 constants right now which you can use to control the duration of the fadein, and the time between the appearance of 2 buttons.
Make sure you set the correct frames for the buttons when you create them. Otherwise, you will just get a bunch of overlapping buttons. If you need you can set the position of the buttons dynamically when you add them to the subview.
Also, I changed the loop mode to use a fast iterator over the array, and keep a incremental index manually.
Im Unsure of what you mean. As for annimation EFFECT, you may want to implement some type of timer, otherwise they will all be added at the same time
If you want a fade in kind of animation then you can achieve something like this -
for(int i =0; i<15;i++)
{
[self.view addSubview:[self.buttonsArray objectAtIndex;i]];
[self performSelector:#selector(showBtn:) withObject:self.buttonsArray objectAtIndex;i] afterDelay:interval];
interval += 0.5f;
}
- (void) showBtn:(UIButton*) btn
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5f];
[btn setAlpha:1.0f];
[UIView commitAnimations];
}
i assume the default alpha of all buttons in array is 0.
pls try this code
for(int i =0; i<15;i++)
{
[self.view addSubview:[self.buttonsArray objectAtIndex;i]];
[self performSelector:#selector(your animated methode) withObject:nil afterDelay:0.1];
}