Update pin to keyboard after autorotation on iPhone/iPad - ios

I have working code that pins UI to keyboard height when it appears:
- (void)keyboardWillShow:(NSNotification *)notification
{
NSDictionary *info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
self.bottomSpacing.constant = kbSize.height + 10;
[self.view layoutIfNeeded];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
self.bottomSpacing.constant = 10;
[self.view layoutIfNeeded];
}
But it has issue when device autorotates: keyboard height changes (ex. on iPad 313 => 398) and 'bottomSpacing' becomes outdated.
How to update it to new keyboard height? Alternatively, is it possible to assign autolayout constraint to keyboard view?

The simplest way is to listen to UIKeyboardWillChangeFrameNotification notification:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillResize:) name:UIKeyboardWillChangeFrameNotification object:nil];
...
- (void)keyboardWillResize:(NSNotification *)notification
{
NSDictionary *info = [notification userInfo];
float keyboardTop = CGRectGetMinY([info[UIKeyboardFrameEndUserInfoKey] CGRectValue]);
float animationDuration = info[UIKeyboardAnimationDurationUserInfoKey] floatValue];
[self.view layoutIfNeeded];
[UIView animateWithDuration:animationDuration animations:^{
self.pinToKeyboardConstraint.constant = keyboardTop;
[self.view layoutIfNeeded];
}];
}
This notification fires whenever the keyboard changes bounds including show and hide events.

Related

Keyboard move up and down with many subviews with uiTextfield

I need to move a keyboard up and down. I have many subviews with many uiTextfields. These subviews has one superview and this superview is in the scroll view.
I can't move up a view using below code:
- (void) keyboardWasShown:(NSNotification *)notification{
NSDictionary *info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey]CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0);
self.Scroll_view.contentInset = contentInsets;
self.Scroll_view.scrollIndicatorInsets = contentInsets;
}
- (void) keyboardWillBeHidden:(NSNotification *)notification{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.Scroll_view.contentInset = contentInsets;
self.Scroll_view.scrollIndicatorInsets = contentInsets;
}
This code working fine when i place all the UITextfields in the ScrollView(Not into the subviews), But i need to do with subview and also move keyboard up and down.
How can i move a keyboard up and down while press keyboard Next/Return key?
Try This:
- (void)animateViewUpToTargetYOrigin:(CGFloat)yValue
{
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardDidChangeFrameNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
CGFloat yOrigin = 0;
CGFloat keyboardYOrigin = [[[note userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;
if (yValue > keyboardYOrigin) {
yOrigin = yValue - keyboardYOrigin;
}
[UIView animateWithDuration:0.3f animations:^{
self.view.frame = CGRectMake(self.frame.origin.x, -yOrigin, self.frame.size.width, self.frame.size.height);
}];
}];
Using this code you only need to call this method in textfield didbeginediting, and pass the yOrigin(textfield)+height(textField) as y value in it.
If you textFields are in Scrollview or any sub view convert their frame values in respect to self.view before sending Y value.
E.g:
CGRect textFieldRectWithRespectToSelfView = [textField.superview convertRect:textField.frame toView:self.view];
[self.view animateViewUpToTargetYOrigin: textFieldRectWithRespectToSelfView.orgin.y + textFieldRectWithRespectToSelfView.size.height];
When you call [textField resignFirstResponder], self.view comes back to its original position. This happens because the UIKeyboardDidChangeFrameNotification always keeps listening to keyboard frame changes.
I do have a demo project in github as an example please refer to it:
https://github.com/subhajitregor/ViewMoveUpExample
In viewDidLoad method
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)keyboardWillHide:(NSNotification *)aNotification
{
// the keyboard is hiding reset the table's height
NSTimeInterval animationDuration =
[[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.origin.y += 150;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
}
- (void)keyboardWillShow:(NSNotification *)aNotification
{
// the keyboard is showing so resize the table's height
NSTimeInterval animationDuration =
[[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.origin.y -= 150;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
}

Enable scrolling content when keyboard appears in iOS

I have an application on iPhone who has much content in viewcontroller. Generally the main content is form. My problem is that I put up keyboard and want to type some value to form fields much of content is invisible. I want to scroll this content when keyboard appear. How can I do this?
My view does'n have scroll view however I tried do this but it don't works.
All hints I found so far concern how to put up used textbox, but this is not my assumption.
This is what i did, I changed the top constraint when keyboard rises up and down like this-
in viewDidLoad call this method-
[self observeKeyboard];
#pragma mark- Keyboard Listen Methods
- (void)observeKeyboard {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillChangeFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
NSDictionary *info = [notification userInfo];
NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [kbFrame CGRectValue];
CGFloat height = keyboardFrame.size.height;
self.COnstraintTopViewVertical.constant=(value of constant)-height;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification {
NSDictionary *info = [notification userInfo];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
self.ConstraintTopViewVertical.constant=reset value;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
You can programmatically change position in the view upon keyboard appearance with the following code:
func keyboardWasShown(notification: NSNotification) {
UIView.animateWithDuration(0.3, animations: { () -> Void in
self.setContentOffset(CGPoint(x: setXOffsetHere, y: setYOffsetHere), animated: true)
})
}
This code will transition the view to the coordinates you specify in .setContentOffset call after keyboard appearance. You still have to get the coordinates, but usually they are pretty straightforward to get from storyboard.
Put all your views in a scroll view
Set an auto layout constraint from the bottom of the scroll view to the bottom of the superview
In viewWillAppear
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillChangeFrame:)
name:UIKeyboardWillChangeFrameNotification object:nil];
Handle the KB notification
- (void)keyboardWillChangeFrame:(NSNotification*)aNotification
{
CGRect kbFrame = [aNotification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect kbWindowIntersectionFrame = CGRectIntersection(self.view.window.bounds, kbFrame);
[UIView animateWithDuration:[aNotification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue] animations:^{
self.scrollVBottomConstraint.constant = kbWindowIntersectionFrame.size.height;
[self.view layoutIfNeeded];
}];
}
what i got from your question is: you are using textfield on UIView which is not on the scrollview, now you have to scroll the UIView when keyboard appears. just do following stuff.
-Give the tag to your textfield.
-suppose tag you have given is 4545646
-do not forgot to assign delegate to your textfield (it will execute below delegate method when you start to edit)
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if (textField.tag == 4545646) {
UIView *contanerView = [self.view viewWithTag:5556466];
[UIView animateWithDuration:0.5 animations:^{
contanerView.frame = CGRectMake(self.view.frame.origin.x+1, -85, self.view.frame.size.width, self.view.frame.size.height-9);
}];
}
}
Change the frame as per your requirement.
and
- (void)textFieldDidEndEditing:(UITextField *)textField {
if (textField.tag == 4545646) {
[textField resignFirstResponder];
UIView *contanerView = [self.view viewWithTag:5556466];
[UIView animateWithDuration:0.5 animations:^{
contanerView.frame = CGRectMake(self.view.frame.origin.x+1, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
}];
}
In viewDidAppear add the following notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyBoardShown:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyBoardDismiss:) name:UIKeyboardWillHideNotification object:nil];
and in keyBoardShown method get the keyboard height
- (void)keyBoardShown:(NSNotification*)notification
{
if(self.view.frame.origin.y>=0)
{
NSDictionary* keyboardInfo = [notification userInfo];
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
// NSLog(#"hihi : %f",keyboardFrameBeginRect.size.height);
keyBoardHeight = keyboardFrameBeginRect.size.height-yDeault+50;
if (keyBoardHeight>0) {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.view.frame = CGRectMake(self.view.frame.origin.x, (self.view.frame.origin.y-keyBoardHeight), self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];
}
}
}
in keyBoardDismiss setback the mainview y coordinate to previous value
-(void)keyBoardDismiss:(NSNotification*)notification{
if(self.view.frame.origin.y<0){
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
self.view.frame = CGRectMake(self.view.frame.origin.x, (self.view.frame.origin.y+keyBoardHeight), self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];
}
}
here yDeault is textfield y coordinate value
yDeault= screenHeight-textField.frame.origin.y+textField.frame.size.height;
Once the keyboard is shown main view will be moved up and once keyboard is dismissed main view will be moved back to the original position
OK. I done this. I need to just add scroll view but in my app probably I have to reconstruct all my view.
No need to add scrollview. Directly you can do this. You can change the self.view.frame without the need of scrollview.

UIWebView automatically is shifted up after keyboard appears

My UIWebView is shifted up when the keyboard appears, and when the keyboard dismisses, the webview does not come back to its previous position. I've checked out the webview's position before and after the keyboard appears, or dismisses. What a surprise, the webview's frame is not changed. But what I've seen before and after are quite different.
Before the keyboard appears:
When the keyboard appears, the webview is shifted up
When the keyboard dismisses, the webview is not shifted down
What I did so far is applying the following techniques I read from others:
1) observe the keyboard notification, and adjust properly after that
observe keyboard notification
2) Change the meta tag, also add "height=device-height" in the meta tag
meta tag
3) Change the webview's attributes:
_webView.contentMode = UIViewContentModeScaleAspectFit;
_webView.scalesPageToFit = YES;
_webView.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
However, all of these suggestion above do not work. Could you please help me?
Note: I use iOS7, XCODE 5
A UIWebView has a UIScrollView in it to manage content which is bigger than the screen. When you adjust the height of a UIScrollView it usually has an impact on it's scroll position. When you shrink the height with a keyboard it causes content to scroll up to keep the text field visible (by modifying the contentOffset), but when you expand the height it just shows more content at the bottom and doesn't change the contentOffset back to the original value.
There are slews of ways to come at this problem and everyone who creates an editable text deals with it at some point. I've used many over the years I'm sure there are probably better ones I haven't even seen.
The way I did it last was by modifying the contentInset of the UIScrollView and saving off the original contentOffset so I can re-populate it later.
Set up your notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification object:nil];
Do stuff on notifications
- (void)keyboardWillShow:(NSNotification *)notification {
NSDictionary *userInfo = [notification userInfo];
CGRect keyboardRect = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
CGFloat keyboardHeight = UIInterfaceOrientationIsPortrait(self.interfaceOrientation)?keyboardRect.size.height:keyboardRect.size.width;
CGFloat duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGFloat animationStyle = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] floatValue];
self.tableViewOffset = self.tableView.contentOffset
UIEdgeInsets contentInsets = self.tableView.contentInset;
contentInsets.bottom = keyboardHeight;
[UIView animateWithDuration:duration delay:0 options:animationStyle animations:^{
self.tableView.contentInset = contentInsets;
} completion:nil];
}
- (void)keyboardWillHide:(NSNotification *)notification {
NSDictionary *userInfo = [notification userInfo];
CGFloat duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
CGFloat animationStyle = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] floatValue];
UIEdgeInsets contentInsets = self.tableView.contentInset;
contentInsets.bottom = 0;
[UIView animateWithDuration:duration delay:0 options:animationStyle animations:^{
self.tableView.contentInset = contentInsets;
self.tableView.contentOffset = self.tableViewOffset;
} completion:nil];
}
What I solved my problem is
1) observe when the keyboard dismisses:
- (void)observeKeyboard {
[NotificationCenter addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)removeObserveKeyboard
{
[NotificationCenter removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
2) When the keyboard is about to hide, we trigger a js to scroll it up.
- (void)keyboardWillHide:(NSNotification *)notification {
[self scrollBackToTop];
}
//- Fix bug: the UIWebView Content is scroll up when the keyboard appears
-(void)scrollBackToTop {
[_webView stringByEvaluatingJavaScriptFromString:#"window.scrollTo(0, 0);"];
}
Thanks to this link : link

Keyboard overlaps Text View

I have tried some solutions that are out there, but they do not work they way I need them to.
I have quite a long text field that will have several paragraphs inside of it. When a user taps on the text field, their keyboard pops up and basically blocks about half the text that's already there and the keyboard prevents them from making any additions to the text field, since the user cannot see what they are typing.
I have tried modifying the frame definition to go above the keyboard, but since the textfield is so long, the user can still go below the keyboard if they add enough text. Wrapping the text view inside a scroll view doesn't do much either.
I am using swift + xcode 6
Here is a screenshot of what I am talking about:
Assuming you're using the autolayout, you can do the following :
In the .h, define a NSLayouConstraint :
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *keyboardHeight;
In the .m :
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillChangeFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification
{
NSDictionary *info = [notification userInfo];
NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [kbFrame CGRectValue];
self.keyboardHeight.constant = keyboardFrame.size.height;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
NSDictionary *info = [notification userInfo];
NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
self.keyboardHeight.constant = 20;
[UIView animateWithDuration:animationDuration animations:^{
[self.view layoutIfNeeded];
}];
}
Then link keyboardHeight with the vertical autolayout constraint between the UITextView and the bottom of the view :
Listen for the UIKeyboardWillShowNotification and UIKeyboardWillHideNotification to adjust the size of your text view as is appropriate. You can get the dimensions of the keyboard via the UIKeyboardFrameEndUserInfoKey of the user dictionary.
E.g. a Swift version of Apple's code:
func keyboardWasShown(aNotifcation: NSNotification) {
let info = aNotifcation.userInfo as NSDictionary?
let rectValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue
let kbSize = rectValue.CGRectValue().size
let contentInsets = UIEdgeInsetsMake(0, 0, kbSize.height, 0)
textView.contentInset = contentInsets
textView.scrollIndicatorInsets = contentInsets
// optionally scroll
let aRect = textView.superview!.frame
aRect.size.height -= kbSize.height
let targetRect = CGRectMake(0, 0, 10, 10) // get a relevant rect in the text view
if !aRect.contains(targetRect.origin) {
textView.scrollRectToVisible(targetRect, animated: true)
}
}

Shift UITextField and UITableView up when keyboard comes up

I have a view with 1. Navigation bar 2.UITableView 3. UITextView.
When I start to edit the textView, a keyboard comes up and I need to animate the TextView and TableView up. I've implemented: https://stackoverflow.com/a/8704371/1808179, but that animated the entire view up, covering the navigation bar.
I tried individually animating the textView like:
- (void)keyboardWillShow:(NSNotification*)notification
{
CGRect chatTextFieldFrame = CGRectMake(chatTextField.frame.origin.x,chatTextField.frame.origin.y-218,chatTextField.frame.size.width,chatTextField.frame.size.height);
[UIView animateWithDuration:0.5 animations:^{ chatTextField.frame = chatTextFieldFrame;}];
}
But it doesn't animate, and it won't synchronously animate alongside the TableView.
What is the best way to animate the tableView and textView up without overlaying the navigation bar?
I generally use the follow snippet when tackling this problem.
Using a UITableView (which is just a subclass of UIScrollView) you should set contentInsets rather then just changing the frame each time. This is especially much nicer in iOS7 with a translucent keyboard.
- (void)viewDidLoad;
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)dealloc;
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
#pragma mark - Keyboard Notifications
- (void)keyboardWillShow:(NSNotification *)notification;
{
NSDictionary *userInfo = [notification userInfo];
NSValue *keyboardBoundsValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGFloat keyboardHeight = [keyboardBoundsValue CGRectValue].size.height;
CGFloat duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
NSInteger animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
UIEdgeInsets insets = [[self tableView] contentInset];
[UIView animateWithDuration:duration delay:0. options:animationCurve animations:^{
[[self tableView] setContentInset:UIEdgeInsetsMake(insets.top, insets.left, keyboardHeight, insets.right)];
[[self view] layoutIfNeeded];
} completion:nil];
}
- (void)keyboardWillHide:(NSNotification *)notification;
{
NSDictionary *userInfo = [notification userInfo];
CGFloat duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
NSInteger animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
UIEdgeInsets insets = [[self tableView] contentInset];
[UIView animateWithDuration:duration delay:0. options:animationCurve animations:^{
[[self tableView] setContentInset:UIEdgeInsetsMake(insets.top, insets.left, 0., insets.right)];
[[self view] layoutIfNeeded];
} completion:nil];
}
If any are wondering, this is how I did it:
- (void)keyboardWillShow:(NSNotification*)notification
{
CGRect chatTableViewFrame = CGRectMake(0,65,320,chatTableView.frame.size.height-180);
[UIView animateWithDuration:0.3 animations:^{ chatTableView.frame = chatTableViewFrame;}];
CGRect chatTextFieldFrame = CGRectMake(chatTextField.frame.origin.x,chatTextField.frame.origin.y-170,chatTextField.frame.size.width,chatTextField.frame.size.height);
[UIView animateWithDuration:0.3 animations:^{ chatTextField.frame = chatTextFieldFrame;}];
[self.chatTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.chat.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
And vice-versa for keyboardWillHide.
Write this line at desired events.
self.view.frame = [[UIScreen mainScreen] applicationFrame];

Resources