I have code that runs fine for my animation. The problem is i want the whole animation to move to the left of the screen then stop and start again. Basically its a bear animating in place but i need the entire animation to move to the left across the screen. I dont want it to animate differently I just need it's x value to change but I'm stuck. Can someone please help. Here's what I have so far.
(void)viewDidLoad
{
[super viewDidLoad];
NSArray *imageNames = #[#"bear1.gif", #"bear2.gif", #"bear3.gif", #"bear4.gif",
#"bear5.gif", #"bear6.gif"];
NSMutableArray *images = [[NSMutableArray alloc] init];
for (int i = 0; i < imageNames.count; i++)
{
[images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
}
// Normal Animation
UIImageView *animationImageView = [[UIImageView alloc] initWithFrame:CGRectMake(60, 95, 50, 50)];
animationImageView.animationImages = images;
animationImageView.animationDuration = 0.5;
[self.view addSubview:animationImageView];
[animationImageView startAnimating];
// Do any additional setup after loading the view, typically from a nib.
}
Add this below the code that you have posted:
[UIView animateWithDuration:5 delay:1 options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat animations:^{
[UIView setAnimationRepeatCount:4];
animationImageView.frame = CGRectMake(160, 95, 50, 50);
} completion:^(BOOL finished) {
animationImageView.frame = CGRectMake(60, 95, 50, 50);
}];
This will move the bear to the right, along the x axis, taking 5 seconds to complete each animation cycle, and repeating the animation 4 times. It will also auto-reverse the animation to its original position after finishing each cycle.
If you don't want it to reverse smoothly and you rather have it snap back to original position after finishing each cycle, just remove the UIViewAnimationOptionAutoreverse flag.
Play around with the options shown to achieve the desired result.
Related
I'm new to the iOS UI development and I need some help to figure out, what is the best way to implement image belt (sequence of images in horizontal belt). I don't need details (someone to write me the code), just guidance what I should focus on learning as a libraries and most important design patterns (by design patters I mean software design for iOS UI).
The task details:
1. I will have image belt - sequence of few related images. This will be my horizontal transition. The transition animation will be simple push animation (something like push CATransion), initiated by swipe left/right. On top of the images there will be overlay with some text, icon info and etc. The overlay info will be the same for all images in the current belt.
2. I will have multiple image belts - this will be my vertical transition. The transition between belts will be triggered by swipe up/down. The different belts will contain unrelated information, so the information shown in overlays from point 1 must be also changed. The animation will be also simple push animation as in point 1.
I probably should inherit UIView and implement my belt as one object, which will consist of different UIView(overlay) and UIImageViews(for the images). Am I on the right track?
Some helpful brainstorm will be highly appreciated.
Yes - I've done many of these. You add a UIView above the top view. I usually use a full-screen one with some alpha so they can see through the core content a little. Then add stuff on top of that which won't change: things like your text, icons, etc... Then on top of that you put the image you want to swipe and add a swipe gesture recognizer, typically one for left and one for right. When they swipe you init a new UIView off the edge of the device, init it with the image, and animate the frames of both left or right, depending on which way they've swiped. Mine are help tutorials showing how to use my app step-by-step so I also init multi-part animations on some of the frames that fly in; that's a nice looking optional effect. Here's the one I use (with the animation support stripped out or it'd be too much code) and there's lots of variations. Edited to note my app doesn't support rotation but if yours does you have to adjust the frames after a rotation.
- (void)init
{
currentPanelNumber = 10;
self = [super initWithNibName:nil bundle:nil];
if (self)
{
[self.view setBackgroundColor:[UIColor clearColor]];
currentPanelNumber = 10;
overlay = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
overlay.backgroundColor = [UIColor colorWithRed:.9 green:.9 blue:.9 alpha:.9];
[self.view addSubview:overlay];
CGRect currentPanelFrame = CGRectMake(267, 175, 494, 444);
currentPanel =
[[HelpView alloc] initWithFrame:currentPanelFrame withImage:[UIImage imageNamed:#"10"]];
currentPanel.frame = currentPanelFrame;
[overlay addSubview:currentPanel];
// ----------------------------------
// Gesture swipes go here
swipeLeftRecognizer =
[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeLeft:)];
[swipeLeftRecognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[overlay addGestureRecognizer:swipeLeftRecognizer];
swipeRightRecognizer =
[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight:)];
[swipeRightRecognizer setDirection:UISwipeGestureRecognizerDirectionRight];
[overlay addGestureRecognizer:swipeRightRecognizer];
swipeDownRecognizer =
[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeDown:)];
[swipeDownRecognizer setDirection:UISwipeGestureRecognizerDirectionDown];
[overlay addGestureRecognizer:swipeDownRecognizer];
UITapGestureRecognizer *tapRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[overlay addGestureRecognizer:tapRecognizer];
skipIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"SkipAndStartIcon"]];
CGSize size = CGSizeMake(84, 124);
skipIcon.frame = CGRectMake((self.view.frame.size.width/2)-(size.width/2), self.view.frame.size.height-size.height-25, size.width, size.height);
[self.view addSubview:skipIcon];
}
- (void)goNext
{
// Clear out all subviews to remove lingering animations
[[currentPanel subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
if(currentPanelNumber>=80)
{
[self closeHelp];
return;
}
NSString *nextImage = [NSString stringWithFormat:#"%i", currentPanelNumber+10];
CGRect nextPanelFrame = CGRectMake(765, 175, 494, 444);
nextPanel = [[HelpView alloc] initWithFrame:nextPanelFrame withImage:[UIImage imageNamed:nextImage]];
nextPanel.frame = nextPanelFrame;
[overlay addSubview:nextPanel];
[UIView animateWithDuration:.2 animations:^
{
nextPanel.frame = currentPanel.frame;
}
completion:^(BOOL finished)
{
currentPanel.image = nextPanel.image;
nextPanel.alpha = 0;
currentPanelNumber += 10;
}
- (void)goPrevious
{
if(currentPanelNumber<=10)
{
return;
}
// Clear out all subviews to remove lingering animations
[[currentPanel subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
NSString *nextImage = [NSString stringWithFormat:#"%i", currentPanelNumber-10];
CGRect nextPanelFrame = CGRectMake(-230, 175, 494, 444);
// nextPanel = [[UIImageView alloc] initWithImage:[UIImage imageNamed:nextImage]];
nextPanel = [[HelpView alloc] initWithFrame:nextPanelFrame withImage:[UIImage imageNamed:nextImage]];
nextPanel.frame = nextPanelFrame;
[overlay addSubview:nextPanel];
[UIView animateWithDuration:.2 animations:^
{
nextPanel.frame = currentPanel.frame;
}
completion:^(BOOL finished)
{
currentPanel.image = nextPanel.image;
nextPanel.alpha = 0;
currentPanelNumber -= 10;
}];
}
I'm using the following code to attempt to flip a UIView. It's a playing card. There's a container view, with two children, front and back. I've read in similar questions here that this should be the correct way to do it, but the actual flip itself is not being performed.
I'm intending for this to animate moving the card to the centre of the screen, and flip it from its back to front. The movement to centre is fine, but the flip never occurs.
If I change the View: argument to self, it flips the entire view controller, and if I leave it on the cardContainer, it does nothing at all.
Puzzled :(
UIView *cardContainer = [[UIView alloc] initWithFrame:CGRectMake(20, self.view.frame.size.height + 20, [Card size].width, [Card size].height)];
[self.view addSubview:cardContainer];
Card *card = _playerOneCards[_playerOneNextCardIndex];
card.frame = CGRectMake(0, 0, [Card size].width, [Card size].height);
card.delegate = self;
[cardContainer addSubview:card];
CardBack *back = [[CardBack alloc] initWithFrame:CGRectMake(0, 0, [Card size].width, [Card size].height)];
[cardContainer addSubview:back];
[UIView transitionWithView:cardContainer
duration:duration
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
back.alpha = 0.0f;
cardContainer.center = self.center;
}
completion:nil];
Try this. The container view has to be placed in the hierarchy before the animation starts.
//Add container views and subviews
[CATransaction flush];
[UIView transitionWithView:cardContainer
duration:duration
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
back.alpha = 0.0f;
cardContainer.center = self.center;
}
completion:nil];
You can also wrap your function up in a dispatch_after call.
For more information check : http://andrewmarinov.com/working-with-uiviews-transition-animations/
I have code for an animating bear but i need to check collision between its animation and a regular UIImageView. Any suggestions? I looked at other answers but my code isn't the same. Here's what I have so far. Or should i use SpriteKit. I'd rather not though.
- (void)viewDidLoad {
NSArray *imageNames = #[#"bear1.gif", #"bear2.gif", #"bear3.gif", #"bear4.gif",
#"bear5.gif", #"bear6.gif"];
NSMutableArray *images = [[NSMutableArray alloc] init];
for (int i = 0; i < imageNames.count; i++) {
[images addObject:[UIImage imageNamed:[imageNames objectAtIndex:i]]];
}
// Normal Animation
UIImageView *animationImageView = [[UIImageView alloc] initWithFrame:CGRectMake(768, 800, 169, 217)];
animationImageView.animationImages = images;
animationImageView.animationDuration = 0.5;
[self.view addSubview:animationImageView];
[animationImageView startAnimating];
[UIView animateWithDuration:7 delay:1 options:UIViewAnimationOptionRepeat animations:^{
[UIView setAnimationRepeatCount:INFINITY];
animationImageView.frame = CGRectMake(-10, 800, 169, 217);
} completion:^(BOOL finished) {
animationImageView.hidden = YES;
}];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
In your animations block you can check to see when the frame of your animating view crosses or is about to cross the frame of your UIImageView. When this condition is met, you stop the animation
I'm doing a countdown clock to my game. I want the numbers to be animated so they come from the middle of the screen and then fade away in the middle. But when I run the code they will come from the right bottom of the screen instead of where I specified it (160,284). What could the problem be?
} else if (startgameEveryInt == 3) {
UIImageView *Object = [[UIImageView alloc] initWithFrame:CGRectMake(160,284,280 ,280)];
[Object setImage:[UIImage imageNamed:#"1.png"]];
[self.view addSubview:Object];
[UIView animateWithDuration:1
animations:^{
Object.alpha = 0;
Object.frame = CGRectMake(160, 284, 50, 50);
}
completion:^(BOOL finished){
startgameEveryInt = 0;
[startgametimer invalidate];
startgametimer = nil;
[self startit];
for (UIView *view in self.view.subviews) {
if (view.tag > 10) {
[view removeFromSuperview];
}
}
}];
}
If you change your CGRect settings to for before the animation-
CGRectMake((self.view.frame.size.width-160)/2, (self.view.frame.size.height-284)/2, 160, 284)
Then changing the size of the object as you did before to
CGRectMake((self.view.frame.size.width-50)/2, (self.view.frame.size.height-50)/2, 50, 50)
This should work for you in the middle of the screen. The X, Y positions of the CGRect will put the top LHS points of your object to that position. This is why your object looked like it was off to the bottom right.
I hope this helps
Cheers, Jim
I have a custom UIView with nested views of type UIImageView, UILabel and UIButton. The view is created in code like this:
- (void)setupView
{
popupView = [[UIView alloc] initWithFrame:CGRectMake(-116, -61, 247, 59)];
popupView.autoresizingMask = 63;
UIImageView *bgImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bubble.png"]];
bgImageView.autoresizingMask = 63;
[popupView addSubview:bgImageView];
[bgImageView release];
textLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 8, 180, 20)];
textLabel.autoresizingMask = 63;
textLabel.font = [UIFont fontWithName:#"DefaultNormal" size:16];
textLabel.text = #"DYNAMIC TEXT";
[popupView addSubview:textLabel];
popupButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
[rightAccessoryButton setImage:[UIImage imageNamed:#"btn-tick.png"] forState:UIControlStateNormal];
popupButton.frame = CGRectMake(208, 8, 32, 32);
popupButton.autoresizingMask = 63;
[popupView addSubview:rightAccessoryButton];
}
I've set all their autoresizingMasks to 63 which is basically everything in the ON position (I don't know a better way of doing that except putting all the constants on a huge line of code!). Then when they need to animate the popup, I do this:
- (void)animateIn
{
float pw = 247;
float ph = 59;
// set the view's initial position
popupView.frame = CGRectMake(-pw*0.005+8, -ph*0.01-2, pw*0.01, ph*0.01);
[self addSubview:popupView];
[UIView animateWithDuration:0.12 delay:0.0 options:UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionLayoutSubviews animations:^(void) {
popupView.frame = CGRectMake(-pw*0.55+8, -ph*1.1-2, pw*1.1, ph*1.1);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^(void) {
popupView.frame = CGRectMake(-pw*0.475+8, -ph*0.95-2, pw*0.95, ph*0.95);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.075 delay:0.0 options:UIViewAnimationOptionLayoutSubviews animations:^(void) {
popupView.frame = CGRectMake(-round(pw/2-8), -ph-2, pw, ph);
} completion:nil];
}];
}];
}
Bit of a complicated looking animation, but effectively this is the same animation as the mapview callout view animation.
Only thing is, it works perfectly on iOS 5 devices, but on iOS 4 devices, everything is wrong! The label doesn't show at all, the button appears and then flies off shrinking into the top right hand corder, and the background image stretches to the wrong size and in the wrong place.
Anyone else had any problems with animations in iOS 4? Do I have to do things differently than how they are currently in order to get it to work?
(1) Are you doing manual layout in a UIView subclass's layoutSubviews implemention? If not, you should not be using UIViewAnimationOptionLayoutSubviews in your options bitmask. I don't know if that's the problem but there's no point adding extra sources of possible error.
(2) When in doubt, use Core Animation. You could describe your animation sequence very handily as a nice CAAnimationGroup.