Rotation of iPad resets animation of views back to start - ios

When I rotate the iPad, all the animated components (e.g. views/buttons) will go back to their original position as to when it was first loaded. Is there any way to prevent this?
Here is how I animate object when I click an button e.g.
- (IBAction)button1Pressed:(id)sender{
[UIView animateWithDuration:ANIMATION_SPEED
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:(void (^)(void)) ^{
self.view.userInteractionEnabled = NO;
_button1.center = CGPointMake(73.01, 419.0);
_button2.center = CGPointMake(750.0, 419.0);
_button3.center = CGPointMake(850.0, 419.0);
_button4.center = CGPointMake(950.0, 419.0);
CGRect theFrame = _loginView.frame;
theFrame.size.width = 576.f;
_View1.frame = theFrame;
_View2.frame = CGRectMake(_button2.center.x + 44.0, _button2.center.y / 2 - 89.0, 0.0, 597.0);
_View3.frame = CGRectMake(_button3.center.x + 44.0, _button3.center.y / 2 - 89.0, 0.0, 597.0);
_4View.frame = CGRectMake(_button4.center.x + 44.0, _button4.center.y / 2 - 89.0, 0.0, 597.0);
}
completion:^(BOOL finished){
self.view.userInteractionEnabled = YES;
}];
}
I'm still quite new so all the details will be appreciated :)

I suggest you to create constraints for the interface you want to animate. Then add reference to your header file for those constraints as for any view element.
When you want to animate a view, you now have to update its constraints and ask to layout the views.
[UIView animateWithDuration:0.2
animations:^{
//in this case, I add 44 to my button Y position, so it will goes down 44px
buttonYConstraint.constant += 44;
[self.view layoutIfNeeded];
}
]
//Now don't forget to update constraints
[self.view updateConstraints];

Turning off auto layout located under the 'Interface builder document' fixed this in quick fashion :)

Related

UIView animation for a shared view in a UIPageController

Much like other apps, my app has a "welcome" page controller with a quick overview of the features. During this overview, I draw a UITabBar and have a circle show where the relevant feature is seen below:
I draw the circle using the following code that is executed every time a page is drawn:
double circleSize = 75;
[circleView removeFromSuperview];
circleView = [[UIView alloc] initWithFrame:CGRectMake(circleX,
circleY,
circleSize,
circleSize)];
circleView.layer.cornerRadius = (circleSize / 2);
circleView.layer.borderColor = [UIColor VancityTransitBlue].CGColor;
circleView.layer.borderWidth = 2;
I wish to have this circle appear to "breath" (grow slowly then shrink back to its original size). I use the exact code from my answer to this question:
[UIView animateWithDuration:1
delay:0
options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
animations:^{
circleView.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
completion:nil];
This circle is shared across three pages of the page controller and draws just fine. The animation works just fine on the first page, periodically works on the second page, and never works on the third page.
How can I have the animation play on every page for every circle view?
Here is a solution that works across all tabs. The animation can be moved around while in progress. You may want to use a better mechanism to manage the animation so that it can be cancelled efficiently. The code below is implemented in the Tab Controller. Ensure -showOverTabBarItem: and -hideCircleView are executed on main thread. It has been built, linked, ran and tested.
Show
-(void)showOverTabBarItem:(CGFloat)x {
[self hideCircleView];
self.circleView.frame =({
CGRect frame = self.circleView.frame;
frame.origin.x = x;
frame;
});
[self.view addSubview:self.circleView];
[UIView animateWithDuration:1
delay:0
options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
animations:^{
self.circleView.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
completion:nil];
}
Hide
-(void)hideCircleView
{
[self.circleView removeFromSuperview];
}
Initialize
Such as in viewDidLoad.
double circleSize = 75;
CGFloat circleY = self.view.bounds.size.height-(circleSize/2);
self.circleView = [[UIView alloc] initWithFrame:CGRectMake(0,
circleY,
circleSize,
circleSize)];
self.circleView.layer.cornerRadius = (circleSize / 2);
self.circleView.layer.borderColor = [UIColor blueColor].CGColor;
self.circleView.layer.borderWidth = 2;
Invoke
Pass the horizontal position to your animation: [self showOverTabBarItem: self.view.bounds.size.width/2];
Keep the view around
This is a critical step: when your -removeFromSuperView, you want to make sure that the object does not get recycled.
#interface TabController ()
#property (nonatomic, retain) UIView * circleView;
#end
Why have you alloc the circle every time a page drawn?
You can remove these lines (just need these for the first init):
if (circleView == nil) {
circleView = [[UIView alloc] initWithFrame:CGRectMake(circleX,
circleY,
circleSize,
circleSize)];
circleView.layer.cornerRadius = (circleSize / 2);
circleView.layer.borderColor = [UIColor VancityTransitBlue].CGColor;
circleView.layer.borderWidth = 2;
}
For add to another page: remove from current page
[circleView removeFromSuperview];
[circleView.layer removeAllAnimations];
and then add it to another page:
[self.view addSubView:circleView];
[UIView animateWithDuration:1
delay:0
options:UIViewKeyframeAnimationOptionAutoreverse | UIViewKeyframeAnimationOptionRepeat
animations:^{
circleView.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
completion:nil];

Move a UIView with start point

I have this code below who move my UIView to left:
- (void)viewDidLoad {
[super viewDidLoad];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:4];
int xOriginal = 91;
CGRect rect = imagem.frame;
int x = rect.origin.x;
int y = rect.origin.y;
int w = rect.size.width;
int h = rect.size.height;
if(x == xOriginal){
imagem.frame = CGRectMake(x+100, y, w, h);
}else{
imagem.frame = CGRectMake(x-100, y, w, h);
}
[UIView commitAnimations];
}
My coordinate of my view is x = 91 (Center of the superView), When I start my app my UIView start left and go to center, instead of center and go to right, Why this is happening?
How to make my UIView start in center (x=91) and go to right (91+100), instead of left to center?
[UIImageView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
imagem.frame=CGRectMake(imagem.frame.origin.x+100, imagem.frame.origin.y, imagem.frame.size.width, imagem.frame.size.height);
} completion:^(BOOL finished) {
//code for completion
NSLog(#"Animation complete");
}];
Autolayout and frame animations are not good friends. Try to animate constraints instead of directly the frame.
You can create outlets of your constraints, and set the constant property of the constraint in your code to move your views.
You also call -[view layoutIfNeeded] to refresh your constraints while in an animation block.
Else you can remove all of your view constraints and animate its frame fearlessly.
Initially image.frame = CGRectMake(91,100,20,20);
So imageview starting point is 0
[UIView animateWithDuration:5.0
animations:^{
//Animation code goes here
image.frame = CGRectMake(191,100,20,20); //Now imageview moves from 0 to 100
} completion:^(BOOL finished) {
//Code to run once the animation is completed goes here
}];
As the other poster says, you can't animate a view's frame in XIBs/storyboards that use AutoLayout.
Instead you have to animate a constraint that's attached to the view.
What you do is to create a constraint (or multiple constraints) and connect it to an IBOutlet. Then, in your animation code, you calculate the changes to the constraint(s) and change the constant for the appropriate constraints.
For example, if you wanted to shift the vertical position of a view, set up a constraint that sets the vertical position of your view, and link it to an IBOutlet called viewConstraint. Then you'd use code like this:
[myView animateWithDuration: .25
animations: ^
{
viewConstraint.constant -= shiftAmount;
[self.view layoutIfNeeded];
}
];

Calling [table reloadData] removes table's position change from [uiview animatewithduration]

There is a button that horizontally shifts my table.
- (void)togglePreferencePageVisibility:(id)sender {
int translation = [self preferencesVisible] ? -PREFERENCE_TRANSLATION_HEIGHT : PREFERENCE_TRANSLATION_HEIGHT;
//animate tableview down
[UIView animateWithDuration:0.3
delay:0
options: UIViewAnimationCurveEaseOut
animations:^{
_table.center = CGPointMake(_table.center.x, _table.center.y+translation);
}
completion:^(BOOL finished){
}];
}
When I call [_table reloadData], the table reverts to its original position. I tried manually readjusting the table position, like so
NSLog(#"before %#", NSStringFromCGRect(_table.frame));
[_table reloadData];
_table.frame = CGRectMake(initialTablePosition.x, initialTablePosition.y+PREFERENCE_TRANSLATION_HEIGHT, _table.frame.size.width, _table.frame.size.height);
NSLog(#"after %#", NSStringFromCGRect(_table.frame));
but no luck. Also the frame's have the same y position before and after.
You need to also adjust the auto layout constraints using the NSLayoutConstraint class. You can add, remove or change the values of NSLayoutConstraints. This is a VERY common question on stack overflow right now, due to the change from iOS 7 to iOS 8.
If you do not adjust the layout constraints then the view will be repositioned back to its original location. reloadData redraws the UITableView which causes the view hierarchy to reexamine its positions e.t.c.
As an example of making a view with a width constraint narrower:
CGRect frame = myView.frame;
frame.size.width -= 100;
//Next line now needed in iOS 8
myWidthConstraint.constant -= 100;
[UIView animateWithDuration:0.5 animations:^{
[myView setFrame:frame];
}];
EDIT: moving back example:
CGRect frame = myView.frame;
frame.size.width += 100;
//Next line now needed in iOS 8
myWidthConstraint.constant += 100;
[UIView animateWithDuration:0.5 animations:^{
[myView setFrame:frame];
}];
When using auto layout, you should not set any frames. If you do, when the view needs to redraw itself, the frame will be reset to the frame defined by its constraints. You should add an IBOutlet to a constraint between your table view and the top (or bottom what ever works for your use) of its superview (I'll call it topCon in the example below).
- (void)togglePreferencePageVisibility:(id)sender {
int translation = [self preferencesVisible] ? -PREFERENCE_TRANSLATION_HEIGHT : PREFERENCE_TRANSLATION_HEIGHT;
//animate tableview down
self.topCon.constant += translation; // this might need to be "-=" depending on whether your constraint is to the top or bottom
[UIView animateWithDuration:0.3
delay:0
options: UIViewAnimationCurveEaseOut
animations:^{
[self.view layoutIfNeeded];
}
completion:^(BOOL finished){
}];
}

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];
}

How to lengthen the UISearchBar in x direction with animation?

I want to lengthen the right search bar 20 px to the left, and shorten left search bar 20 px to the right with animation. How can I do that?
CGRect leftFrame = self.leftSearchBar.frame;
//leftFrame.origin.x = leftFrame.origin.x - 20;
leftFrame.size.width = leftFrame.size.width - 40;
CGRect rightFrame = self.rightSearchBar.frame;
rightFrame.origin.x = rightFrame.origin.x - 40;
rightFrame.size.width = rightFrame.size.width + 40;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:0.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.leftSearchBar.frame = leftFrame;
self.rightSearchBar.frame = rightFrame;
[UIView commitAnimations];
It doesn't work. It first resizes views without animation, then moves the right view with animation.
Assuming you've not changed the anchor points, or anything like that, simply expanding the width will make it stretch to the right. Wrap this within a UIView animation block, and it should animate according to the specification within the question, as so:
UISearchBar* searchbar = ...; // However you've created your UISearchBar, we'll refer to it as 'searchbar'
CGRect searchFrame = searchbar.frame;
[UIView animateWithDuration:0.8
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
searchFrame.size.width += 30;
searchbar.frame = searchFrame;
}
completion:nil];
You'll need to make sure the += 30 doesn't get called more than once, as otherwise you'll be expanding by 30 points each time this is called. If you know the size before hand, you could simply substitute it with = size + 30, which is a safer bet incase you call the animation more than once.

Resources