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];
}
Related
I need to animate a UIImageView inside my application, and cyclically change the UIImage inside it, making it look like an animated photo slideshow.
Right now I'm using an NSTimer to fire every N seconds the UIImage change and the animation itself:
- (void)viewDidLoad {
// NSArray initialization
NSTimer *timer = [NSTimer timerWithTimeInterval:16
target:self
selector:#selector(onTimer)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[timer fire];
[super viewDidLoad];
}
This is the onTimer selector code:
- (void) onTimer {
// cycle through max 9 images
if(imageIndex > 8)
imageIndex = 0;
// set the image
[_imageContainer setImage:[images objectAtIndex:imageIndex]];
// reset width and height of the UIImage frame
CGRect frame = [_imageContainer frame];
frame.size.width -= 170.0f;
frame.size.height -= 100.0f;
[_imageContainer setFrame:frame];
// fade in
[UIView animateKeyframesWithDuration:2.0f delay:0.0f options:0 animations:^{
[_imageContainer setAlpha:1];
} completion:^(BOOL finished) {
// image movement
[UIView animateKeyframesWithDuration:12.0f delay:0.0f options:0 animations:^{
CGRect frame = [_imageContainer frame];
frame.size.width += 170.0f;
frame.size.height += 100.0f;
[_imageContainer setFrame:frame];
} completion:^(BOOL finished) {
// fade out
[UIView animateKeyframesWithDuration:2.0f delay:0.0f options:0 animations:^{
[_imageContainer setAlpha:0];
} completion:nil];
}];
}];
imageIndex++;
}
This seem a very raw but "working" way to achieve what I want but I recognize it might not be the ideal way.
Is there any better method to achieve what I'm looking for?
Updated Answer For Fade Animation
- (void)viewDidLoad
{
[super viewDidLoad];
// self.animationImages is your Image Array
self.animationImages = #[[UIImage imageNamed:#"Image1"], [UIImage imageNamed:#"Image2"]];
// make the first call
[self animateImages];
}
- (void)animateImages
{
static int count = 0;
UIImage *image = [self.animationImages objectAtIndex:(count % [animationImages count])];
[UIView transitionWithView:self.animationImageView
duration:1.0f // animation duration
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
self.animationImageView.image = image; // change to other image
} completion:^(BOOL finished) {
[self animateImages]; // once finished, repeat again
count++; // this is to keep the reference of which image should be loaded next
}];
}
- (IBAction)press:(id)sender {
UIImage *bomb = [UIImage imageNamed:#"bom"];
UIImageView *bom =[[UIImageView alloc] initWithImage:bomb];
[bom setFrame: CGRectMake(83,115,35,35)];
[self.view addSubview:bom];
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationCurveEaseIn animations:^{
[bom setFrame:CGRectMake(149,47,35,35)];
}
completion:^(BOOL finished)
{
[bom setFrame:CGRectMake(134,40,60,55)];
[bom setImage:[UIImage imageNamed:#"splash"]];
hits++;
_hit.text=[NSString stringWithFormat:#"%i",hits];
}];
}
Here is my code! The object bom here handles the imageview for splash.png image and i want that image to be appeared only for 0.5 sec when each time the button is pressed
You could set up an NSTimer that calls a method which hides the image. You would have to keep a reference to the bomb.
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(hideImage) userInfo:nil repeats:NO];
-(void)hideImage {
self.bomb.hidden = YES;
}
I try to create a UITexView with auto scrolling when press button start. And have a button stop, when pressed it will stop scrolling. Pressing button start again and it will continues to scroll down. How to handle this function.
I have research some code that this code below work with me.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(#"%f %f",_txvSentence.contentSize.width , _txvSentence.contentSize.height);
if (scrollingTimer == nil) {
scrollingTimer = [NSTimer scheduledTimerWithTimeInterval:(35.0/1000.0)
target:self
selector:#selector(autoscrollTimerFired:)
userInfo:nil
repeats:YES];
NSLog(#"%#",scrollingTimer);
}
}
- (void)autoscrollTimerFired:(NSTimer*)timer {
CGPoint scrollPoint = self.txvSentence.contentOffset;
//scrollPoint = CGPointMake(scrollPoint.x, scrollPoint.y + 1);
scrollPoint = _txvSentence.contentOffset;
scrollPoint.y= scrollPoint.y+1;
[_txvSentence setContentOffset:scrollPoint animated:NO];
//[self.txvSentence setContentOffset:scrollPoint animated:NO];
}
But i cannot stop this animation. And how to set dynamic duration such as when come to the end of text it automatically stop.
Sorry because my bad english. If not understand please tell me where I will explain it clearly.
Try this:
self.scrollView.scrollEnabled = NO;
CGFloat scrollHeight = 100;
//===
- (void) spinWithOptions: (UIViewAnimationOptions) options {
// this spin completes 360 degrees every 2 seconds
[UIView animateWithDuration:10
delay:0
options:options
animations:^{
self.scrollView.contentOffset = CGPointMake(0, scrollHeight);
}
completion:^(BOOL finished) {
if (finished) {
if (animating) {
// if flag still set, keep spinning with constant speed
[self spinWithOptions: UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction];
} else if (options != UIViewAnimationOptionCurveEaseOut) {
// one last spin, with deceleration
[self spinWithOptions: UIViewAnimationOptionCurveEaseOut];
}
}
}];
}
- (void) startAnimating {
if (!animating) {
animating = YES;
[self spinWithOptions: UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction];
}
}
- (void) stopAnimating {
// set the flag to stop spinning after one last 90 degree increment
animating = NO;
}
You can use NSTimer.
// Global var
CGFloat scrollHeight = MAX_HEIGHT;
CGFloat currentOffsetY = 0.0f;
NSTimer *timer;
self.timer = [NSTimer scheduledTimerWithTimeInterval:YOUR_TIME_INTERVAL target:self selector:#selector(scrollText:) userInfo:nil repeats:YES];
- (void)scrollText:(NSTimer *)timer {
currentOffsetY++;
if (currentOffsetY >= MAX_HEIGHT) {
[self.timer invalide];
}
self.scrollView.contentOffset = CGPointMake(0, currentOffsetY);
}
// Your button action
- (void)stopAnimation:(UIButton *)button {
[self.timer invalide];
}
I'm new to iOS, i want to update the text in ViewDidLoad() function.
This is my button function, When button is clicked animation take place and also adds the value "1" to "resultText.text"
- (IBAction)oneButton1:(id)sender {
oneBtn2.userInteractionEnabled = YES;
CGRect frame = oneBtn1.frame;
CGRect frame1 = reffButton.frame;
frame.origin.x = frame1.origin.x;
frame.origin.y = frame1.origin.y;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration: 3.0];
[UIView animateWithDuration:3.0 animations:^{
[oneBtn1 setTransform:CGAffineTransformMakeScale(.4, .4)];
} completion:^(BOOL finished) {
oneBtn1.hidden = YES;
price = [resultText.text intValue];
[resultText setText:[NSString stringWithFormat:#"%i", price+1]];
}];
oneBtn1.frame = frame;
[UIView commitAnimations];
}
Problem: The above text value is 1 but in ViewDidLoad is 0 ,
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"%#", resultText.text); // output is 0 instead of 1;
}
Please anyone tell me how to update the text value in ViewDidLoad function ...
ViewDidLoad calling only once when the object is creating .So you can't update the thing in ViewDidLoad.ViewDidLoad use for initialising the parameters and set the initial settings when an object creating.
This is because every time your view will load it create new object of your textField, thats why you are unable to fetch previous (because its new textField not old one).So you have to save your text some where, for example you can use NSUserDefaults
SetText
NSString *result=[NSString stringWithFormat:#"%i", price+1];
[resultText setText:];
//Also set it to NSUserDefaluts
[[NSUserDefaults standardUserDefaults] setValue:result forKey:#"key"];
[[NSUserDefaults standardUserDefaults] synchronize];
Get Text
- (void)viewDidLoad
{
[resultText setText:[[NSUserDefaults standardUserDefaults] valueForKey:#"key"]];
NSLog(#"%#", resultText.text);
}
EDIT
You can make animation afterButton click, so call this method in button click event
-(void)animateImage
{
if ([resultText.text isEqualToString:#"3"]) {
//make your animation
}
}
You can use a method to do that
- (void)updateLabel {
oneBtn2.userInteractionEnabled = YES;
CGRect frame = oneBtn1.frame;
CGRect frame1 = reffButton.frame;
frame.origin.x = frame1.origin.x;
frame.origin.y = frame1.origin.y;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration: 3.0];
[UIView animateWithDuration:3.0 animations:^{
[oneBtn1 setTransform:CGAffineTransformMakeScale(.4, .4)];
} completion:^(BOOL finished) {
oneBtn1.hidden = YES;
price = [resultText.text intValue];
[resultText setText:[NSString stringWithFormat:#"%i", price+1]];
}];
oneBtn1.frame = frame;
[UIView commitAnimations];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self updateLabel];
NSLog(#"%#", resultText.text); // output is 0 instead of 1;
}
I have a multiple images to show in imageview using cross dissolve animation and taping on image displays detail about image. Following is the code working but tap on imageview is failing when it's animating from one image to another.
Code for attaching single tap gesture recogniser to UIImageview and starting animation timer.
self.imageView.userInteractionEnabled = YES;
self.singleTapGestureRecogniser = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showDetails)];
self.singleTapGestureRecogniser.numberOfTapsRequired = 1;
self.singleTapGestureRecogniser.cancelsTouchesInView = NO;
[self.imageView addGestureRecognizer:self.singleTapGestureRecogniser];
[self startAnimationTimer];
- (void)startAnimationTimer
{
if(!self.timer && ![self.timer isValid]) {
self.timer = [NSTimer scheduledTimerWithTimeInterval:5.0
target:self
selector:#selector(startAnimation)
userInfo:nil
repeats:YES];
[self.timer fire];
}
}
Single tap on imageview works fine unless following code is executing! I have to tap 3-4 times to open details about image.
- (void)startAnimation
{
[UIView transitionWithView:self.imageView duration:2.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^ {
currentImageIndex = ++currentImageIndex % self.images.count;
[self.imageView setImage:[[self.images objectAtIndex:currentImageIndex] image]];
} completion:^(BOOL finished) {
}
];
}
Could someone please suggest me how to get rid of this issue please.
set UIViewAnimationOptionAllowUserInteraction in the options like so
[UIView transitionWithView:self.imageView duration:2.0
options:UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowUserInteraction
animations:^ {
currentImageIndex = ++currentImageIndex % self.images.count;
[self.imageView setImage:[[self.images objectAtIndex:currentImageIndex] image]];
} completion:^(BOOL finished) {
}
];