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

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

Related

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

How to make UIView move by click?

I'm not sure whether I can describe it properly. It's a kind of UIView, and we see only it's part (with arrow,maybe. on the bottom of screen,maybe). User can click on it, and this view appears fullscreen(usually developer leaves there some additional information). How can I make it?
Try this:
-(void)show
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,viewObj.frame.origin.y,viewObj.frame.size.width, viewObj.frame.size.height)];//Here "viewObj.frame.origin.y" means 568
[UIView animateWithDuration:0.5 animations:^
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,0,viewObj.frame.size.width, viewObj.frame.size.height)];
}
completion:^(BOOL finished)
{
}];
}
-(void)hide
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,viewObj.frame.origin.y,viewObj.frame.size.width, viewObj.frame.size.height)];//Here "viewObj.frame.origin.y" means 0
[UIView animateWithDuration:0.5 animations:^
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,568,viewObj.frame.size.width, viewObj.frame.size.height)];
}
completion:^(BOOL finished)
{
}];
}
i just put the logic that just setting of view Y coordinate of That View and when user click on Button. that et animation and at the re setting the view frame with Y coordinate setting like:
yourview.frame = CGRectMake(0,280,320,568);
[UIView animateWithDuration:2
delay:0.1
options: UIViewAnimationOptionTransitionFlipFromBottom
animations:^{
yourview.frame = CGRectMake(0, 0, 320, 568);
}
completion:^(BOOL finished){
}];
Also see this example:
https://github.com/crocodella/PullableView
Here above github demo this same that you are looking for its output like:
Look at UIView reference:
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html
Specifically:
#property(nonatomic) CGPoint center
And
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations
Example:
[UIView animateWithDuration:2.0 animations:^{
myView.center = CGPointMake(self.view.center.x, self.view.center.y + myOffset);
}];
Duration is in seconds. In this case, 2 seconds.
If you're using AutoLayout, you probably want to change the layout constant, rather then center property.
About Layout Constrains:
https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutConstraint_Class/NSLayoutConstraint/NSLayoutConstraint.html
Look at constant property. You can also drag a constrain outlet from Interface Builder and access its constant. It's really simple once you get to know it a bit.

Label animation moving text - iOS

I'm using this block to animate a pulse on my text and when I do, the text moves to the right some and jerks back. Seems like it is due to some padding or something being added by interface builder.
[UIView animateWithDuration:0.5 animations:^{
// grow the label up to 130%, using a animation of 1/2s
myLabel.transform = CGAffineTransformMakeScale(1.3,1.3);
} completion:^(BOOL finished) {
// When the "grow" animation is completed, go back to size 100% using another animation of 1/2s
[UIView animateWithDuration:0.5 animations:^{
myLabel.transform = CGAffineTransformIdentity;
}];
}];
Reduce the anchorPoint by a factor of 1.3 on the way back. Change your code to this -
CGPoint anchorPoint = myLabel.layer.anchorPoint;
[UIView animateWithDuration:0.5 animations:^{
// grow the label up to 130%, using a animation of 1/2s
myLabel.transform = CGAffineTransformMakeScale(1.3,1.3);
} completion:^(BOOL finished) {
// When the "grow" animation is completed, go back to size 100% using another animation of 1/2s
myLabel.layer.anchorPoint = CGPointMake(anchorPoint.x/1.3, anchorPoint.y/1.3);
[UIView animateWithDuration:0.5 animations:^{
myLabel.transform = CGAffineTransformIdentity;
}];
}];
I tried your code. It is working fine for the labels which text is fitted in the label properly or those labels have the text alignment center.
So my suggestion is if you have label having static or fixed text then give the background color to label and check for label text if it is too large then make it as such so that text fit to label properly. Then your code will work fine.
Now if you have dynamic text then try to calculate the label width dynamically as below
UIFont *font = [UIFont systemFontOfSize:9.0];
CGSize stringSize;
stringSize = [myLabel.text sizeWithFont:font constrainedToSize:CGSizeMake(1000, myLabel.frame.size.height) lineBreakMode:UILineBreakModeWordWrap];
Then assign stringSize.width as mylabel width. Means here you will change the width of label dynamically.
Then you code will work fine as you want.
You should try this code i think it will help you,first it will Zoom your image to 130 % then it will zoom out your image to the original size
[UIView animateWithDuration:0.5 animations:^{
myLabel.transform = CGAffineTransformMakeScale(1.3,1.3);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 animations:^{
myLabel.transform = CGAffineTransformMakeScale(1,1);
myLabel.hidden=YES;
}];
}];

Transforming a subview of UIScrollView

I am trying to reproduce an effect like the iOS 7 app switcher where I can scroll between smaller, transformed views. My current obstacle is getting the contentOffset
In order to do this, I have added a scrollView to my view, and sized it to the bounds of the view. I then create a container view that holds on to all the 'cards' -- it is this container view to which I apply the transform.
Anyway, the issue I am having is with adjusting where a particular card appears after it has the transform applied -- right now, I am unable to adjust the contentOffset during the transform in a manner that is smooth.
Anyway, code would help! Here it is:
NSInteger idx = selectedCardIndex;
if (TransformApplied)
{
[UIView animateWithDuration:0.5 animations:^{
[self.container setTransform:CGAffineTransformIdentity];
[self.container setFrame:CGRectOffset(self.container.frame, (1-ScaleFactor)/2 * NumCards * ScreenWidth, 0)];
[self.scrollView setContentSize:self.container.frame.size];
[self.scrollView setContentOffset:CGPointMake(ScreenWidth * idx, 0) animated:NO];
[self.scrollView setPagingEnabled:YES];
} completion:^(BOOL finished) {
TransformApplied = NO;
}];
}
else
{
[UIView animateWithDuration:0.5 animations:^{
[self.container setTransform:CGAffineTransformMakeScale(ScaleFactor, ScaleFactor)];
[self.container setFrame:CGRectOffset(self.container.frame, (-1)*((1-ScaleFactor)/2) * NumCards * ScreenWidth, 0)];
[self.scrollView setContentSize:CGSizeMake(ScreenWidth * ScaleFactor * NumCards, ScreenHeight * ScaleFactor)];
[self.scrollView setContentOffset:CGPointMake(ScaleFactor * ScreenWidth * idx, 0) animated:NO];
[self.scrollView setPagingEnabled:NO];
} completion:^(BOOL finished) {
TransformApplied = YES;
}];
}
More
I am noticing that everything is smooth when applying the identity transform, but not when applying the smaller transform, I get a weird 'jump' in the frame before the animation.
If i comment out the content offset adjustment in the scale transform (the bottom block) then everything runs smoothly, but the contentOffset is wrong after the scale transform.
Lastly, calling setContentOffset:animated: results in a wonky animation so that is a no-go.
Any help greatly appreciated!!!!
UPDATE
I've looked in to anchor point/ position properties on CALayer, and I've got the animation effects working perfectly with this:
NSInteger idx = selectedCardIndex;
if (TransformApplied)
{
[UIView dd_AnimateWithDuration:0.5 animations:^{
[self.container setTransform:CGAffineTransformIdentity];
[self.scrollView setContentOffset:CGPointMake(ScreenWidth * idx, 0) animated:NO];
[self.scrollView setPagingEnabled:YES];
} completion:^(BOOL finished) {
TransformApplied = NO;
}];
}
else
{
CGPoint anchor = CGPointMake((idx * ScreenWidth + ScreenWidth/2)/CGRectGetWidth(self.container.frame), 0.5f);
[self.container.layer setAnchorPoint:anchor];
CGPoint position = CGPointMake((anchor.x) * self.container.frame.size.width, self.container.layer.position.y);
[self.container.layer setPosition:position];
[UIView dd_AnimateWithDuration:0.5 animations:^{
[self.container setTransform:CGAffineTransformMakeScale(ScaleFactor, ScaleFactor)];
[self.scrollView setPagingEnabled:NO];
} completion:^(BOOL finished) {
TransformApplied = YES;
}];
}
However, now i've got to figure out a way to get rid of all the extra space in the scrollview without allowing the position of the container to change....
I have had a similar issue a long time ago about the position of a view. After a long research, I ended up with the UIView documentation. It says about transform and frame properties of a UIView with a warning:
Warning:
If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.
Changing the frame rectangle automatically redisplays the receiver without invoking the drawRect: method. If you want the drawRect: method invoked when the frame rectangle changes, set the contentMode property to UIViewContentModeRedraw.
Changes to this property can be animated. However, if the transform property contains a non-identity transform, the value of the frame property is undefined and should not be modified. In that case, you can reposition the view using the center property and adjust the size using the bounds property instead.
So, the basic idea is that, you shouldn't rely on or change frame when your view's transform contains a non-identity transform.
And the more important idea, always give a chance to the official documentation before looking elsewhere.
I hope this helps.

UILabel always animates to same spot

I have a UILabel called "nameLabel" and I have it inside an animation block so that this happens:
_nameLabel.alpha = 1;
CGAffineTransform translate = CGAffineTransformMakeTranslation(50, 50);
_nameLabel.transform = translate;
I thought that animates the UILabel to the spot I specify but it just animates from the above spot to the place where I have it in the Interface Builder. Any help here?
Can you post the animation block and other associated code? I am not sure what CGAffineTransformMakeTranslation does with the label, but if you want to animate the frame location, you can use this:
CGRect frame = _nameLabel.frame;
frame.origin.y = 100; //Desired height, origin.x can be modified as well.
//You can also change the frame size here but it wont work on UILabels, you will need `CGAffineTransformScale` for that.
[UIView animateWithDuration: 1.5
delay:0.0
options:UIViewAnimationCurveEaseInOut | UIViewAnimationOptionBeginFromCurrentState
animations:^ {
[_nameLabel setFrame:frame];
}
completion:^ (BOOL finished) {
}];
Edit: The other way:
CGRect frame = _nameLabel.frame;
frame.origin.y = 100;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.5];
[_nameLabel setFrame: newFrame];
[UIView commitAnimations];
Current state is probably the current location of the label, try that first but if nothing happens, remove UIViewAnimationOptionBeginFromCurrentState or set the frame of the label to another location before the animation, and move it to its initial (the one in the xib file) position in the animation block, its your call.
Watch out because Autolayout cause a lot of problems.
Try to deselect 'Use Autolayout'
It solves to me all the problems trying to translate objects.

Resources