Why moving UIView is not moving UIImageView on same view? - ios

I have an ImageView on a UIView. I'm trying to move view keyboard size but all content move properly instead of UIImageView.
-(void) keyboardWillShow:(NSNotification *) notification {
NSDictionary* keyboardInfo = [notification userInfo];
// Work out where the keyboard will be
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
// Work out animation duration
NSTimeInterval animationDuration =[[keyboardInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationOptions keyboardAnimationCurve = [[keyboardInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
// Animate this
[UIView animateWithDuration:animationDuration
delay:0.0
options:keyboardAnimationCurve
animations:^(){
self.view.frame = CGRectOffset(self.view.frame, 0, -keyboardFrameBeginRect.size.height);
}
completion:NULL];
[UIImageView animateWithDuration:animationDuration
delay:0.0
options:keyboardAnimationCurve
animations:^(){
self.imgBankLogo.frame = CGRectOffset(self.imgBankLogo.frame, 0, -keyboardFrameBeginRect.size.height);
}
completion:NULL];
}
Anyone had same issue or some suggestion? I even tried to move UIImage but it is not moving.
As you can see everything moved except imageview!

If you are trying to move two views together, and one is a subview of the other, you shouldn't need to animate them individually.
Animating the parent view should move all of the subviews with it automatically. Trying to animate them individually at the same time can cause weird results in my experience. This animation block should be all you need. You may also want to check the Auto Layout settings in the views File Inspector tab.
If you want to perform more than one animation at once you can add multiple calls in the same animation block as well.
[UIView animateWithDuration:animationDuration
delay:0.0
options:keyboardAnimationCurve
animations:^(){
//you can add multiple here
self.view.frame = CGRectOffset(self.view.frame, 0, -keyboardFrameBeginRect.size.height);
}
completion:NULL];

Related

Why moving parent view is not moving subview?

I have a view as follow:
In my code I want to move this view keyboard size:
-(void) keyboardWillShow:(NSNotification *) notification {
NSDictionary* keyboardInfo = [notification userInfo];
// Work out where the keyboard will be
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
// Work out animation duration
NSTimeInterval animationDuration =[[keyboardInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationOptions keyboardAnimationCurve = [[keyboardInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
// Animate this
[UIView animateWithDuration:animationDuration
delay:0.0
options:keyboardAnimationCurve
animations:^(){
self.view.frame = CGRectOffset(self.view.frame, 0, -keyboardFrameBeginRect.size.height);
}
completion:NULL];
}
It is moving everything to top except child views. Then I tried to move child views to the top as follow:
-(void) keyboardWillShow:(NSNotification *) notification {
NSDictionary* keyboardInfo = [notification userInfo];
// Work out where the keyboard will be
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
// Work out animation duration
NSTimeInterval animationDuration =[[keyboardInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationOptions keyboardAnimationCurve = [[keyboardInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
// Animate this
[UIView animateWithDuration:animationDuration
delay:0.0
options:keyboardAnimationCurve
animations:^(){
self.view.frame = CGRectOffset(self.view.frame, 0, -keyboardFrameBeginRect.size.height);
self.memberNumberLayout.frame = CGRectOffset(self.memberNumberLayout.frame, 0, -keyboardFrameBeginRect.size.height);
}
completion:NULL];
}
self.memberNumberLayout is a subview of main UIView. But it is not moving. What could force sub view to stay there? Could it be because of constrains? As you can see to subviews and one label has not move with their parent view!
Constrains
While it is really hard to tell the problem from your constraints hierarchy screenshots, I think the problem is related to top constraints for self.memberNumberLayout my suggestions are the following:
1- use constrains instead of frames to animate your views by using IBOutlet from the top constraints of the container view then use the constant e.g self.containerConstraint.constant = keyboardSize * -1;
2- use scrollviews for such problems. UIScrollView is a great view for moving views up when keyboard appears or disappears, also this is can be very helpful when you run your app on different devices. Refer to this question for more information: How to make a UITextField move up when keyboard is present?
The problem is that you are saying self.view.frame =. You can't do that — this view is fixed as a subview of the window. Give self.view a content view the same size at itself (pinned to all four sides), with all other views inside it, and when the time comes, move the content view. Moreover, you've got constraints on these views (auto layout), so you must not change the frame of the content view; to move it, change its constraints.

iOS Animating main UIViewController's View height

I have a text field pinned to the bottom of my main UIViewController's view (self.view), and when the user clicks on it this function is called (via a UIKeyboardWillShowNotification) which will alter the height of the self.view.frame:
-(void)keyboardWillShow: (NSNotification*) notification {
NSDictionary* info = [notification userInfo];
CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGFloat textFieldHeight = activeField.frame.size.height;
CGPoint textFieldOrigin = activeField.frame.origin;
textFieldOrigin.y += textFieldHeight;
CGRect visibleRect = self.view.frame;
visibleRect.size.height -= keyboardSize.height;
if (!CGRectContainsPoint(visibleRect, textFieldOrigin)) {
CGRect r = self.view.frame;
r.size.height -= keyboardSize.height;
[UIView animateWithDuration:1.0
animations:^{
self.view.frame = r;
}];
}
}
It resizes the self.view.frame fine, so it is all being called and run, but for some reason refuses to animate it over a second - it just appears in place immediately.
What do I need to do in order to animate this change in height?
If you have auto layout on you shouldn't change the frame directly, instead you should change on of the constrains.
Add an IBOutlet to the constrain (the bottom constrain), and change the constant like so:
myTextFieldConstrain.constant -= YOUR_VALUE
Also, if you want it to animate, call [YOURSUPERVIEW layoutIfNeeded]; after you change the constant.
Example:
[UIView animateWithDuration:1.0
animations:^{
myTextFieldConstrain.constant -= YOUR_VALUE;
[YOURSUPERVIEW layoutIfNeeded];
}];
Try to dispatch it with a slight delay, like:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[UIView animateWithDuration:1.0
animations:^{
self.view.frame = r;
}];
}
It usually makes the trick.

Autolayout Issue with growing UITextView above keyboard

I have a UIViewController with a main view. Within that view I have a red UIView that has a UITextView inside, that I would like to grow vertically when text is written. I'm able to have this effectively done if the redView initially starts somewhere in the middle of the screen and doesn't move based on the keyboard popping up by just modifying the UITextViewHeightConstraint that I made.
-(void)textViewDidChange:(UITextView *)textView {
[self.textView setScrollEnabled:NO];
CGSize newSize = [textView sizeThatFits:CGSizeMake(textView.frame.size.width, 999)];
if (newSize.height > textView.frame.size.height) {
self.textViewHeight.constant = newSize.height;
}
}
When I dock the redView that includes the UITextView subview to the bottom of the screen, my code appropriately will bring the view above the keyboard nicely, using the following code:
-(void)adjustViewForKeyboardNotification:(NSNotification *)notification {
NSDictionary *notificationInfo = [notification userInfo];
CGRect finalKeyboardFrame = [[notificationInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
//Get AnimationCurve and AnimationDuration for keyboard popping up.
UIViewAnimationCurve animationCurve = (UIViewAnimationCurve) [[notificationInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
NSTimeInterval animationDuration = [[notificationInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
finalKeyboardFrame = [self.view convertRect:finalKeyboardFrame fromView:self.view.window];
CGRect textBarFrame = self.redView.frame;
textBarFrame.origin.y = finalKeyboardFrame.origin.y-textBarFrame.size.height;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
[UIView setAnimationBeginsFromCurrentState:YES];
self.redView.frame = textBarFrame;
[UIView commitAnimations];
}
However, when I start typing and it comes time for the UITextView to expand, the redView is sent back down and is docked to the bottom of the screen (under the keyboard) - where it then expands vertically as I would have liked. I've tried adjusting the constraints in many different ways but haven't found a solution. I've tried setting the frame of the redView manually but that doesn't seem to work either (likely because of auto layout being enabled).
Any advice or tips would be greatly appreciated!

improve the animation when showing text view on top of keyboard

I am doing an animation to show the text view on top keyboard when UIKeyboardWillShowNotification is being broadcasted like following
-(void) keyboardWillShow:(NSNotification *)notification{
// get keyboard size and loctaion
NSDictionary *info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
NSNumber *duration = [notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
__block CGRect containerFrame = containerView.frame;
containerFrame.origin.y = self.view.bounds.size.height - (kbSize.height + containerFrame.size.height);
[UIView animateWithDuration:[duration doubleValue]
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
containerView.frame = containerFrame;
} completion:^(BOOL finished) {
nil;
}
];
}
An animation is not good enough.If you can give it a try and will see small issue at the end of animation.
I googled and found out that there is another way to do an animation and it works perfectly :
-(void) keyboardWillShow:(NSNotification *)note{
// get keyboard size and loctaion
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue: &keyboardBounds];
NSNumber *duration = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSNumber *curve = [note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey];
// Need to translate the bounds to account for rotation.
keyboardBounds = [self.view convertRect:keyboardBounds toView:nil];
// get a rect for the textView frame
CGRect containerFrame = containerView.frame;
containerFrame.origin.y = self.view.bounds.size.height - (keyboardBounds.size.height + containerFrame.size.height);
// animations settings
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:[duration doubleValue]];
[UIView setAnimationCurve:[curve intValue]];
// set views with new info
containerView.frame = containerFrame;
// commit animations
[UIView commitAnimations];
}
However, according to the documentation, we are not recommended to use this animation in Ios 4 and later on...
I can not tell any differences between my codes compared to the latter one. Why my codes can not do perfect animation. Please help if you have any ideas.
It's the animation curve. The example you cite is matching its animation curve as well its duration to those of the keyboard. Your code doesn't. Your structure should look more like this:
NSNumber* curve = info[UIKeyboardAnimationCurveUserInfoKey]; // *
NSNumber* duration = info[UIKeyboardAnimationDurationUserInfoKey];
[UIView animateWithDuration:duration.floatValue delay:0
options:curve.integerValue << 16 // *
animations: ^{ // ...

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