Accessing the current position of UIView during animation - iphone

I am trying to find the current position of an iPhone ImageView that is animating across the screen.
I create and animate the imageView like so
-(IBAction)button:(UIButton *)sender{
UIImageView *myImageView =[[UIImageView alloc] initWithImage:
[UIImage imageNamed:#"ball.png"]];
myImageView.frame = CGRectMake(0, self.view.frame.size.height/2, 40, 40);
[self.view addSubview:myImageView];
[myArray addObject:myImageView];
[UIView animateWithDuration:.5
delay:0
options:(UIViewAnimationOptionAllowUserInteraction) // | something here?)
animations:^{
myImageView.frame = CGRectOffset(myImageView.frame, 500, 0);
}
completion:^(BOOL finished){
[myArray removeObject:myImageView];
[myImageView removeFromSuperview];
[myImageView release];
}
];
}
then to detect the current CGPoint of the imageView I call this method every 60th of a second
-(void)findPoint{
for (UIImageView *projectile in bullets) {
label.text = [NSString stringWithFormat:#"%f", projectile.center.x];
label2.text = [NSString stringWithFormat:#"%f", projectile.center.y];
}
}
However this only gives me the point where the animation ends, I want to get the current CGPoint of the image that is animating across the screen. Is there an option that I need to apply other than UIViewAnimationOptionAllowUserInteraction to do this? If not, how do I get the current position of an animating imageView?

You can use the presentationLayer - a property of the CALayer that "provides a close approximation to the version of the layer that is currently being displayed". Just use it like this:
CGRect projectileFrame = [[projectile.layer presentationLayer] frame];

Swift 5:
Get temporary position and size (CGRect) during the animation with:
let currentFrame = projectileFrame.layer.presentation()!.frame

Related

drawing NSString using drawRect and animate it

I am drawing a NSString using drawRect and is it possible for me to animate this NSString once it has been drawn? I want it to fade in/out after 3.0 seconds. How can I do so?
Make a UILabel, then use animation to perform your desires
- (void)faceInLabel{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
label.text = #"My String";
[myView addSubview:label];
label.alpha = 0;
[UIView animateWithDuration:0.5 animations:^{
label.alpha = 1;
}
completion:^(BOOL finished)
{
[NSTimer timerWithTimeInterval:3 target:self selector:#selector(fadeOutLabel) userInfo:nil repeats:NO];
}];
}
- (void)fadeOutLabel
{
[UIView animateWithDuration:0.5 animations:^{
label.alpha = 0;
}];
}
You cannot directly fade the drawn string itself. You can fade layers and you can fade views. Draw the string onto one of these and fade the layer or view. This is generally most easily done with a UILabel or CATextLayer, but you can draw onto your own layer and fade that if you prefer.

Animation on UIButton Click in iPhone

Everybody..
How to set animation on button click ?
I have two buttons, both have different frame..
First CGRectMake (10 , 10 , 100 , 80 ); It has Black Image,
Second CGRectMake (200, 10 , 210 , 80 ); It has White Image,
When I click on First button of those, It should be animate to move from one frame to another frame..
Only seen like first's button Black Image move to second button location.. Like Image changes of Buttons..
After clicked button frame does not change... Should be remain as First and Second..
I have tried but not got the exact
buttonFirst.frame = buttonSecond.frame;
buttonFirst.center = buttonSecond.center;
buttonFirst.transform = CGAffineTransformMakeTranslation( buttonSecond.frame.origin.x - buttonFirst.frame.origin.x , buttonSecond.frame.origin.y - buttonFirst.frame.origin.y);
How to animate this ?
Editting :
I need to move one checkers from one CGRect to Another CGRect.. So, It want to display like moving checkers, But i dont want to change CGRect, Only button images looks like that...
Please tell me..
Thanks...
very simple logic
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.20f];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationBeginsFromCurrentState:YES];
[firstButton setFrame:CGRectMake(5, 50, 30, 30)];//moves to second button place
[secondButton setFrame:CGRectMake(5, 5, 30, 30)];//moves to first button place
[UIView commitAnimations];
use the logic accordingly to your use..
well..
you can try this link
[UIView beginAnimation/endAnimation] bock
CGRect oldRectFirst = buttonFirst.frame;
CGRect oldRectSecond = buttonSecond.frame;
[UIView animateWithDuration:0.2f animations:^{
buttonFirst.frame = oldRectSecond;
buttonSecond.frame = oldRectFirst;
}];
Here is example from working program:
[self.buttonFirst setUserInteractionEnabled:NO];
[UIView transitionWithView:self.buttonFirst
duration:1.0
options:UIViewAnimationOptionTransitionFlipFromLeft | UIViewAnimationOptionCurveLinear
animations:^{
buttonFirst.frame = buttonSecond.frame;
buttonFirst.center = buttonSecond.center;
}
completion:^(BOOL finished){
[self.buttonFirst setUserInteractionEnabled:YES];
}];
Finally i got the answer...
I have set two button in two separate view. after set one timer, and move first button image to another button's position..
Here is a sample code for that..
Step 1 : Set view with Timer
UIView *oldView = [[UIView alloc] init];
oldView = [viewArray objectAtIndex:selectedIndex];
UIView *newView = [[UIView alloc] init];
newView = [viewArray objectAtIndex:[sender tag]];
oldRect = [oldView frame];
newRect = [newView frame];
movingTimer = [[NSTimer alloc] init];
movingTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(movingCheckers:) userInfo:nil repeats:YES];
imageViewMove = [[UIImageView alloc] init];
[imageViewMove setFrame:oldRect];
[imageViewMove setImage:[UIImage imageNamed:blackManName]];
[self.view bringSubviewToFront:imageViewMove];
[self.view addSubview:imageViewMove];
Step 2 : Moving Image to second position
CGPoint aPoint = CGPointMake(newRect.origin.x - oldRect.origin.x, oldRect.origin.y - newRect.origin.y);
imageViewMove.frame = CGRectMake(imageViewMove.frame.origin.x + (aPoint.x / 6) , imageViewMove.frame.origin.y - (aPoint.y / 6), imageViewMove.frame.size.width, imageViewMove.frame.size.height);
if (imageViewMove.frame.origin.x >= newRect.origin.x)
{
[selectButton setBackgroundImage:nil forState:UIControlStateNormal];
[moveButton setBackgroundImage:imageViewMove.image forState:UIControlStateNormal];
[imageViewMove removeFromSuperview];
[movingTimer invalidate];
}
Now its work.....

collision of two images, problem with the declaration

I have a method with an image "imageView":
- (void)createNewImageView {
// Get the view's frame to make it easier later on
UIImage *image = [UIImage imageNamed:#"abouffer_03.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// Add it at a random point
[imageView setCenter:[self randomPointSquare]];
[[self view] addSubview:imageView];
// Animate it into place
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:8.0f];
[imageView setCenter:CGPointMake(240, 160)];
[UIView commitAnimations];
[imageView release];
}
and another image "viewToRotate" (IBOuutlet defined in .h and interface builder)
And I want to check the collision with this method :
- (void)myRunloop
{
// check collision
if( CGRectIntersectsRect(imageView.frame, viewToRotate.frame) )
{
viewToRotate.alpha=0.2;
}
}
But xcode always give me the error :"imageView undeclared" and I don't know how to solve this . I don't wanna define it again in this method.
I just'd been through a similar problem actually when you set the frame of the imageView on line
[imageView setCenter:CGPointMake(240, 160)];
the imageView gets settled at that point in the memory, It's just that due to being in animation block it's showing you the transition that imageView is being moved towards the destination but in actual the view's coordinates are assigned with the destination location, you can confirm it by logging coordinates right after the line of code. If you really need to do this the similar way, you can use the timer instead of the animation block and animate yourself. But I circumvent this problem by using the animationDelegate. Just set animation delegate to self and define animationDidStopSelector and you're up. You're animationDidstopSelector will get fired when the animation's ended and hence the object reached it's final destination or you can say there's a collision (on UI). Hope that helps
Here's a code sample:
- (void)createNewImageView {
// Get the view's frame to make it easier later on
UIImage *image = [UIImage imageNamed:#"abouffer_03.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
// Add it at a random point
[imageView setCenter:[self randomPointSquare]];
[[self view] addSubview:imageView];
// Animate it into place
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidStop:)];
[UIView setAnimationDuration:8.0f];
[imageView setCenter:CGPointMake(240, 160)];
[UIView commitAnimations];
[imageView release];
}
your animationDidStopSelector will be just like:
-(void)animationDidStop:(id)sender {
//This is almost similar to collision detection, you can do something here
}
imageView is a local variable to the function createNewImageView and hence cannot be accessed by myRunloop
If you have declared imageView as an IBOutlet
you can set the image like this
UIImage *image = [UIImage imageNamed:#"abouffer_03.png"];
imageView.image = image
In Interface (.h file) declare like this
UIImageView *imageView;
And In your createNewImageView() method.Use the
imageView = [[UIImageView alloc] initWithImage:image];
You can assign a tag to the image view so you can find it later in the other method:
[imageView setTag:1];
// in myRunloop
UIImageView* imageView = [[self view] viewWithTag:1];

transition animation on only a part of the screen

I am displaying two images in my iPhone app, one on top, one on the bottom. They cover the entire screen. The user, with a swipe gesture, can change either of the images, depending on where the swipe started.
I want the image to change with an animated transition. It currently works without animation, or with the entire screen transitioning. Is it possible to make the transition occur over part of the screen?
I load the images for the first time (in viewDidLoad) thus:
// top image
UIImage *topImage = [UIImage imageNamed:#"top1.png"];
CGRect topframe = CGRectMake(0.0f, 0.0f, 320.0f, 240.0f);
UIImageView *topView = [[UIImageView alloc] initWithFrame:topframe];
topView.image = topImage;
[self.view addSubview:topView];
[topView release];
// bottom image
UIImage *bottomImage = [UIImage imageNamed:#"bottom1.png"];
CGRect bottomframe = CGRectMake(0.0f, 240.0f, 320.0f, 240.0f);
UIImageView *bottomView = [[UIImageView alloc] initWithFrame:bottomframe];
bottomView.image = bottomImage;
[self.view addSubview:bottomView];
[bottomView release];
When I detect a swipe, and detect which of the two images are to be changed, I call a routine like this one:
- (void)changeTopImage:(NSString *)newImage {
UIImage *topImage = [UIImage imageNamed:newImage];
CGRect topframe = CGRectMake(0.0f, 0.0f, 320.0f, 240.0f);
UIImageView *topView = [[UIImageView alloc] initWithFrame:topframe];
topView.image = topImage;
[self.view addSubview:topView];
[topView release];
}
Essentilly, I'm continually loading images on top of each other. Is that the best way to do it, especially in terms of memory management?
Everything else I've tried, using techniques such as below, make the entire screen transition:
[UIView beginAnimations:nil context:nil];
...
[UIView commitAnimations];
Thanks for any leads on which way I should be going on this.
well, an easy way could be this (repeat for the bottomImage):
don't release topView when you load it the first time in your method,
but declare it in your .h file,
and use a tempView too:
#interface YourClass: UIViewController{
UIImageView *topView;
UIImageView *tempView;
}
this way you can call them to move them and remove them when you load a new image
then in .m:
EDIT: some correction (see coco's comments):
[a] [b] line 4 = [c] line 11:
- (void)changeTopImage:(NSString *)newImage {
UIImage *topImage = [UIImage imageNamed:newImage];
//CGRect topframe = CGRectMake(0.0f, 0.0f, (320.0f + 320), 240.0f);
CGRect topframe = CGRectMake((0.0f + 320), 0.0f, 320.0f, 240.0f);
tempView = [[UIImageView alloc] initWithFrame:topframe];
//topView.image = topImage;
tempView.image = topImage;
[self.view addSubview:tempView];
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[UIView beginAnimations:#"animation" context:NULL];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
tempView.center = topView.center;
// do this to push old topView away, comment next line if wanna new image just cover it
//topView.center = CGPointMake(topView.x - 320, topView.y);
topView.center = CGPointMake(topView.center.x - 320, topView.center.y);
// call a method when animation has finished:
[UIView setAnimationDidStopSelector:#selector(endOfAnimation:finished:context:)];
[UIView commitAnimations];
}
- (void)endOfAnimation:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
[topView removeFromSuperview];
topView = tempView;
[tempView release];
tempView = nil;
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}
- (void)dealloc {
if (tempView != nil) {
[tempView release];
}
[topView release];
[super dealloc];
}

How to add a moving text in iPhone

I want to add some text which is a long text lets say a story and I want it to be presented in a moving up fashion. That is it will be displayed in a box and the text will be moved line by line to show the whole story. So one line gets out of the box from top and other comes from the bottom. Like a HTML marquee behavior.
You should look into whether or not UIScrollView's contentOffset property is animatable using UIView animation blocks.
If it's not, then you could try using an NSTimer and in its function, either set the contentOffset or call [scrollView scrollRectToVisible:desiredContentFrame animated:YES]; where desiredContentFrame.origin.y is just a little bit lower than what you previously had it at (depending on the scroll speed you want). Then play around with the firing frequency of your timer and the desiredContentFrame.origin.y's delta to see what looks best and has the best performance.
Here's a quick hack showing both ways:
- (void)startAnimTimer
{
currentRect = CGRectMake(0, 0, 1, 1);
[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(doScroll) userInfo:nil repeats:YES];
}
- (void)startAnimUIView
{
[UIView beginAnimations:#"scrollUIViewAnim" context:nil];
[UIView setAnimationDuration:20.0];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
CGPoint newContentOffset = CGPointMake(0, scrollView.contentSize.height);
scrollView.contentOffset = newContentOffset;
[UIView commitAnimations];
}
- (void)loadView {
[super loadView];
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(5, 5, 200, 200)];
scrollView.contentSize = CGSizeMake(200, 1000);
scrollView.backgroundColor = [UIColor magentaColor];
CGFloat y = 10;
CGFloat yDelta = 21;
for(int i = 0; i < 47; i++)
{
// Add some UILabels to the scrollview just so we can see it animating
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, y, 180, 20)];
label.text = [NSString stringWithFormat:#"Cheezburger %d", i];
[scrollView addSubview:label];
[label release];
y += yDelta;
}
[self.view addSubview:scrollView];
// Comment out one of these
//[self startAnimTimer];
[self startAnimUIView];
}
- (void)doScroll
{
CGFloat scrollDelta = 1.0f;
CGRect newRect = CGRectMake(0, currentRect.origin.y + scrollDelta, currentRect.size.width, currentRect.size.height);
// Scroll the scrollview to the next position
[scrollView scrollRectToVisible:newRect animated:YES];
currentRect = newRect;
}
This method may help (or not):
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
If not, just make a big UILabel and animate its frame using a CABasicAnimation.
I think you want to look at the Scroll View (UIScrollView) in the iPhone SDK.
http://developer.apple.com/IPhone/library/documentation/UIKit/Reference/UIScrollView_Class/Reference/UIScrollView.html
Depending on your implementation, you may not be able to use it "out of the box" but it should provide the functionality you seem to be describing. I'm not sure it will do the auto-scroll thing but that should be pretty easy to implement... maybe.... But, I'm still confident it could be done.