How to get the position of oldest object made during animation? - ios

I make every second a UIImageView of a french frie called FrenchFrie. I also let them move along the screen with an animation.
-(void)FrenchFrieRain{
FrenchFrie = [[UIImageView alloc] initWithFrame:CGRectMake(randomX,0,30,30)];
FrenchFrie.image = [UIImage imageNamed:#"FrenchFriesMCDonalds"];
FrenchFrie.userInteractionEnabled = YES;
[self.view addSubview:FrenchFrie];
[FrenchFrieArray addObject: FrenchFrie];
[self letFrenchFrieFall];
}
-(void)letFrenchFrieFall {
[UIView animateWithDuration:10.0f delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
FrenchFrie.frame = CGRectMake(randomX, (int)[[UIScreen mainScreen] bounds].size.height + 40, FrenchFrie.frame.size.width, FrenchFrie.frame.size.height);
} completion:^(BOOL finished){
[[FrenchFrieArray objectAtIndex:0] removeFromSuperview];
}];
}
I need the position of the frie during the animation. I do this with the following code:
FrenchFrieFrame = [[FrenchFrie.layer presentationLayer] frame];
From NSLogging I know that with this code I get the position of the newest frie but I need the position of the oldest one. How can I get the position of the oldest French Frie?
Any help would be really appreciated!

You are keeping track of the order in which you create FrenchFries in your FrenchFrieArray. So, the item at index 0 will be the oldest FrenchFrie, always. You could use:
FrenchFrieFrame = [[FrenchFrieArray[0].layer presentationLayer] frame];
For this to work, you should also remove the FrenchFrie from the array, besides removing it from the view:
[[FrenchFrieArray objectAtIndex:0] removeFromSuperview];
[[FrenchFrieArray removeObjectAtIndex:0];

Related

UIImageView size suddenly change after set new image

I have a problem that I can't find the errors as titled. And I have searched so many times that similar or related questions, that can't solve.
I am building an App that can change the Image of A UIImageView with a button. everything is fine until I use another button to change the size of imageView (with UIView animateWithDuration + CGAffineTransformMakeRotation), then use that button for changing image.
strange output with no errors happen! the imageview size change back and the position move to other places.
Sorry about my poor english.
with graphics,
I have this view [no size changed view][1]
I use animateWithDuration + CGAffineTransformMakeRotation change the size & orientations, to make the view fullscreen like this [size changed view][2]
Then I change this image of this view by imageView.image = newImage(UIImage)
However, the view change to this [strange view][3] either the size or position are changed!
But, there's nothing if I change the image at Step 1 (no orientation & set frame)
Please help, I can't find the errors because there only one place that change the size&orientation of the view.
I wonder there is something UIImage would affect the UIImageView. But I can't find the answer.
(the photos are down below)
this is the code to rotate the image ivew
if there is already set image, after rotation, the image is also fine
But problem get after rotation, and then set the new image to the image view
-(void)transformToDirection:(NSInteger)dir
{
rotation = M_PI_2;
CGFloat screenW = [[UIScreen mainScreen] bounds].size.width;
CGFloat screenH = [[UIScreen mainScreen] bounds].size.height;
CGRect portraitFrame = _imageVIew.frame;
CGRect landscapeFrame = CGRectMake(0, 0, screenW, screenH);
switch (dir) {
case UIInterfaceOrientationPortrait:
{
[UIView animateWithDuration:1 delay:0 options:0 animations:^{
_imageVIew.transform = CGAffineTransformMakeRotation(3/4 * rotation);
[_imageVIew setFrame:portraitFrame];
}completion:^(BOOL finished){
isFullScreen = false;
}];
}
break;
case UIInterfaceOrientationLandscapeRight:
{
[UIView animateWithDuration:1 delay:0 options:0 animations:^{
_imageVIew.transform = CGAffineTransformMakeRotation(rotation);
[_imageVIew setFrame:landscapeFrame];
}completion:^(BOOL finished){
isFullScreen = true;
}];
}
break;
case UIInterfaceOrientationLandscapeLeft:
{
[UIView animateWithDuration:TIME_ANIMATE_FULLSCREEN delay:0 options:0 animations:^{
_imageVIew.transform = CGAffineTransformMakeRotation(-rotation);
[_imageVIew setFrame:landscapeFrame];
}completion:^(BOOL finished){
isFullScreen = true;
}];
}
break;
default:
break;
}
}
this is the image view set image (all new images are the same size), which is called by a button.
dispatch_async(dispatch_get_main_queue(), ^{
if (loadedimage) {
self.imageVIew.image = loadedimage;
} else {
self.PBMainImageVIew.image = nil;
dlog(#"request image failed");
}
});

Resetting scale after transformation

_cardView =[card initCard];
[self.view addSubview:_cardView];
_cardView.transform=CGAffineTransformScale(CGAffineTransformIdentity, 0.1, 0.1);
[UIView animateWithDuration:0.3
animations:^{
_cardView.transform=CGAffineTransformIdentity;
}];
I have a view which I animate to make it seem as if it is expanding from a point (similar to the animation of an app being opened). This view is returned from [card initCard], with card being a custom class, and assigned to _cardView. Using CGAffineTransformScale I first decrease the scale and then animate the increase of the scale. This works perfectly for the first card that is shown. However, when _cardView is set to nil and a new card is assigned to it, the same transformation and animation code produce the wrong animation which makes the view increase in scale before decreasing. I assume that the problem is in making the scale 0.1,0.1 but I have not been able to solve this.
Setting to nil:
else if (sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled || sender.state == UIGestureRecognizerStateFailed)
{
if(sender.view.center.x>0){
[UIView animateWithDuration:0.2 animations:^{
CGRect rect=[sender.view frame];
rect.origin.x=([self.view frame].size.width/2)-129.5;
[sender.view setFrame:rect];
sender.view.alpha = 0.8;
}];
}else{
[UIView animateWithDuration:0.5 animations:^{
_protoypeView.alpha=0.0;
_protoypeView=nil;
_cardView=nil;
[self nextCard];
}];
}
}
and function nextCard:
-(void)nextCard{
if(cardNumber>[questionArray count]-1){
NSLog(#"Out of cards");
}else{
QuestionCard *card=[[QuestionCard alloc]init];
NSArray* array =[[NSArray alloc]initWithArray:questionArray[cardNumber]];
card.questionString=array[3];
card.whenPosted=array[0];
card.isAnon=array[2];
card.user=array[1];
card.replies=array[4];
card.profileImg=array[5];
_cardView =[card initCard];
[self.view addSubview:_cardView];
_cardView.alpha=0.0;
_cardView.transform=CGAffineTransformScale(CGAffineTransformIdentity, -1, -1);
_cardView.transform=CGAffineTransformIdentity;
[UIView animateWithDuration:1 animations:^{
_cardView.alpha=0.7;
}];
UIPanGestureRecognizer * pan1 = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(handlePanImage:)];
pan1.minimumNumberOfTouches = 1;
[_cardView addGestureRecognizer:pan1];
yOfView=[_cardView frame].origin.y+([_cardView frame].size.height/2);
cardNumber++;
}
}
First case of CGAffineTransform (after successful query to Parse database):
[UIView animateWithDuration:0.5 animations:^{
_protoypeView.alpha=0.0;
}completion:^(BOOL finished){
QuestionCard *card=[[QuestionCard alloc]init];
NSArray* array =[[NSArray alloc]initWithArray:questionArray[cardNumber]];
card.questionString=array[3];
card.whenPosted=array[0];
card.isAnon=array[2];
card.user=array[1];
card.replies=array[4];
card.profileImg=array[5];
_cardView =[card initCard];
[self.view addSubview:_cardView];
_cardView.transform=CGAffineTransformScale(CGAffineTransformIdentity, 0.0, 0.0);
[UIView animateWithDuration:0.3
animations:^{
_cardView.transform=CGAffineTransformIdentity;
}];
UIPanGestureRecognizer * pan1 = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(handlePanImage:)];
pan1.minimumNumberOfTouches = 1;
[_cardView addGestureRecognizer:pan1];
yOfView=[_cardView frame].origin.y+([_cardView frame].size.height/2);
cardNumber++;
}];
Found the problem - [self nextCard] was called in animations, but should be called in completion.

Resize views on click with animation

I'm trying to make a user interface that animates when I click on it.
This is my sketch:
It starts with the mapview as small as on the left sketch. The rest is filled with a tableview. Now when I click on the map view it slides to the bottom like on the right sketch so the mapview fills the most off the screen. Ans visa versa when I click on the small Tableview.
How can I achieve this?
I thought off creating a View and then add mapview and tableview as subviews, but then I don't know how to animate that. Did some real simple animations until now.
Can someone point me in the right direction?
NSNumber isMapExpanded = 0;
- (void) expandMap
{
[UIView animateWithDuration:1.0
delay:0.2
options:nil
animations:^{
if([isMapExtended integerValue] == 0)
{
mapview.frame = CGRectMake(mapview.frame.origin.x, mapview.frame.origin.y, mapview.frame.size.width, mapview.frame.size.height + heightTobeExpanded);
tableView.frame = CGrectMake(tableView.frame.origin.x, tableView.frame.origin.y - heightTobeExpanded, tableView.frame.size.width, tableView.frame.size.height + heightTobeExpanded);
}
else if([isMapExtended integerValue] == 1)
{
mapview.frame = CGRectMake(mapview.frame.origin.x, mapview.frame.origin.y, mapview.frame.size.width, mapview.frame.size.height - heightTobeExpanded);
tableView.frame = CGrectMake(tableView.frame.origin.x, tableView.frame.origin.y + heightTobeExpanded, tableView.frame.size.width, tableView.frame.size.height - heightTobeExpanded);
}
}
completion:nil];
}
something along the lines of:
[UIView animateWithDuration:1.0
delay:0
options:nil
animations:^{
map.frame = CGRectMake(0,0,newheight,320);
table.frame = CGrectMake(0,newheight,screenheight-newheight, 320);
}
completion:nil];
you can call something like that in your click method. this is just an example - you should not use hardcoded numbers in your application :)
Please try this code:-
[UIView beginAnimations:#"Expand MApview" context:nil];
[tblView setFrame:CGRectMake(0, self.view.frame.size.height-50, tblView.frame.size.width,tblView.frame.size.height)];
[mapview setFrame:CGRectMake(0,0,mapview.frame.size.width,self.view.frame.size.height-50)];
[UIView setAnimationDelay:2];
[UIView commitAnimations];
As you already stated, put both the map and the table in a superview.
On click, you may use the following :
[UIView animateWithDuration:0.5 animations:^{
map.frame = CGRectMake(x,y,width,newHeight); //Set the frame to be with the new map height
tableView.frame = CGRectMake(x,NewYCoordinate,width,height); //Move the tableView down
}];
- (void) changeFrameBetweenMapAndTable
{
[UIView animateWithDuration:1.0
delay:0.5
options:nil
animations:^{
CGRect mapRect = mapview.frame;
mapview.frame = tableView.frame;
tableView.frame = mapRect;
}
completion:nil];
}

Drop image and release when it goes out of bounds

I am new to programming in Objective-C, and am currently having an issue with the code below. I am trying to make an image drop when a button is touched, and it simply freezes when trying to do so. It needs to drop the image until it reaches the bottom of the screen, which then it should be released.
- (IBAction)itemDrop:(UIButton *)sender{
if (strncmp([[sender currentTitle] UTF8String], [copyPrimaryArray[0] UTF8String], 2) == 0)
{
UIImage *bubblImage = [UIImage imageNamed:#"Red_apple.png"];
UIImageView *appleImg = [[UIImageView alloc] initWithImage:bubblImage];
appleImg.translatesAutoresizingMaskIntoConstraints = NO;
[appleImg setContentMode:UIViewContentModeScaleAspectFit];
[appleImg sizeToFit];
[self.view addSubview:appleImg];
NSLog(#"You clicked the Apple");
int i = 0;
CGPoint coordinates = sender.frame.origin;
CGFloat x = coordinates.x;
CGFloat y = coordinates.y;
CGFloat z = UIScreen.mainScreen.bounds.size.height;
while (y < z) {
[UIView beginAnimations:nil context:nil];
appleImg.center = CGPointMake(x, y+i);
[UIView commitAnimations];
i++;
}
}
}
You do not need to move the image view one point at a time manually. That's what I seem to understand from your use of the while loop. Objective-c does a lot of things for you.
UIImage *bubblImage = [UIImage imageNamed:#"Red_apple.png"];
UIImageView *appleImg = [[UIImageView alloc] initWithImage:bubblImage];
// Set the frame of the original position here, for example:
CGRect originalPosition = CGRectMake(0, 0, appleImg.frame.size.width, appleImg.frame.size.height);
appleImg.frame = originalPosition;
// Then animate it to the new position:
[UIView animateWithDuration:1.0
animations:^{
CGRect newPosition = CGRectMake(0, 640, appleImg.frame.size.width, appleImg.frame.size.height);
appleImg.frame = newPosition;
}
completion:^(BOOL finished) {
NSLog(#"completion block"); // You can set the completion block to nil if you have nothing to do here.
}];
Make sure to start using block based animations.
The use of UIView's beginAnimations:context is highly discouraged since iOS 4.0.

UIView animationWithDuration recursive cause jitter

I tried to set the property as atomic but it doesn't seems to work anyway. Here's the code. It move a label displaying the song name being played. And sometime it start jittering as if the label was supposed to be at two places at the same time. Any clue ? Some lock property maybe...
- (void)animateSongLabel
{
if (!self.player.rate) {
[UIView animateWithDuration:.5 animations:^{
self.songLabel.left = 25.f;
}];
return;
}
[UIView animateWithDuration:.25 delay:0. options:UIViewAnimationOptionCurveLinear animations:^{
self.songLabel.left -= 15.f;
} completion:^(BOOL finished) {
if (self.songLabel.right < -10.f) {
self.songLabel.left = 320.f;
}
[self animateSongLabel];
}];
}
The rock-bottom simplest way to make text that just sits there and scrolls sideways is to display an animated UIImage or animated UIImageView - especially the former, because it animates forever, which is probably what you want. Generate the successive UIImage objects in code by drawing your text slightly offset each time, and hand them to animatedImageWithImages:duration:. Now wherever you show that image, it will be animating.
Here's some sample code to get you started (tweak to get precisely the effect you have in mind):
NSString* s = #"Mister Dobbalena, Mister Bob Dobbalena";
NSMutableArray* marr = [NSMutableArray array];
UIFont* f = [UIFont fontWithName:#"Helvetica" size:12];
float w = [s sizeWithFont:f].width;
for (int offset = 0; offset < w; offset++) {
UIGraphicsBeginImageContextWithOptions(self.iv.frame.size, NO, 0);
[s drawAtPoint:CGPointMake(10-offset,20) withFont:f];
[marr addObject: UIGraphicsGetImageFromCurrentImageContext()];
UIGraphicsEndImageContext();
}
UIImage* im = [UIImage animatedImageWithImages:marr duration:20];
self.iv.image = im;

Resources