I use the following when show/hide the keyboard:
- (void)keyboardWasShown:(NSNotification *)notification
{
NSDictionary *info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
self.scrDetails.contentInset = contentInsets;
self.scrDetails.scrollIndicatorInsets = contentInsets;
}
- (void)keyboardWillHide:(NSNotification *)notification
{
/* Set to NO so after the keyboard is hidden, the size goes back to normal */
self.automaticallyAdjustsScrollViewInsets = NO;
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.scrDetails.contentInset = contentInsets;
self.scrDetails.scrollIndicatorInsets = contentInsets;
[self.view layoutIfNeeded];
}
But for some reason even though the size is set correctly when dismissing the keyboard
(lldb) po self.scrDetails.contentInset
(top = 0, left = 0, bottom = 0, right = 0)
the effect is not shown on the device/simulator(the scrollbar remain at the previous keyboard up position)
See the image
I use autolayout, so I am not setting the contentSize directly.
Any suggestions what might help tracking this down?
You can use third party class TPKeyboardAvoiding. It manage keyboard.
Link : https://github.com/michaeltyson/TPKeyboardAvoiding
Related
I've been struggling with this keyboard and scrollview issue for quite sometime now. I'm trying to make a chat room similar to What'sApp and iMessage. I have UITabBar as a root view controller. For the chat room view I have a toolbar at the bottom that contains UITextView and UIButton the issue is that when the keyboard is presented it pushes the content view out of the screen and I can't see about 1/5 of the top of the content view. I tried playing with the numbers and still can't get it to work properly. Any help would be greatly appreciated.
- (void)keyboardWasShown:(NSNotification *) aNotification {
NSDictionary *info = [aNotification userInfo];
CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
// the hardcoded 49 is the height of the UITabBar at the bottom below the input toolbar
UIEdgeInsets contentInsets = UIEdgeInsetsMake((-keyboardSize.height+49), 0.0, (keyboardSize.height-49), 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
// CGRect aaRect = self.view.frame;
// aaRect.size.height -= keyboardSize.height;
// if (!CGRectContainsPoint(aaRect, self.activeTextView.frame.origin)) {
// [self.scrollView scrollRectToVisible:self.activeTextView.frame animated:NO];
// }
CGPoint scrollPoint = CGPointMake(0, self.scrollView.contentInset.bottom);
[self.scrollView setContentOffset:scrollPoint animated:true];
[self.view addGestureRecognizer:self.tapRecognizer];
}
- (void)keyboardWillBeHidden:(NSNotification *) aNotification {
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
[self.view removeGestureRecognizer:self.tapRecognizer];
}
I met the same problem long time ago. My solution is to listen keyboard frame did change notification(because different keyboard has different frame). And I think it is easier to adjust the frame of scroll view rather than content offset.
I am new in iOS. I am making a chat application so I have a UITextField below the UITableView and UITextField and UITableView are inside the UIScrollView (I have disable the scroll in scrollview by self.scrollView.scrollEnabled = NO;).
When I tap on UITextField, the keyboard was shown, so I move the UITextField to above keyboard follow Managing the Keyboard doc
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, self.activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:self.activeField.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
self.activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
self.activeField = nil;
}
With this code, my TextField move to above keyboard successful
But the problem is: In the TableView, when the keyboard was shown I cannot scroll to see some items on top (about 2 items).
For example, if my tableview have 10items, when the keyboard was shown, i can only see 8items, 2 rest items still exist but I cannot scroll to them
Here is my Demo Project
I think maybe the content inset of UITableView is wrong but I don't know how to fix it.
Any help would be great appreciated
Use Autolayout insteads of contentInsets
In ViewController.h
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *botConstraint;
In ViewController.m
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
self.botConstraint.constant = kbSize.height;
[self.view layoutIfNeeded];
//...
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
self.botConstraint.constant = 0.0f;
[self.view layoutIfNeeded];
//...
}
botConstraint is UITextField/UITableView/UIScrollView .bottom = fatherView.bottom in your Main.storyboard
I have textViews in a tableView. When textViews (towards the bottom of the tableView) get selected the keyboard pops up, and hides the textView, and you can't scroll down either. So I added the following code:
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
myTableView.contentInset = contentInsets;
myTableView.scrollIndicatorInsets = contentInsets;
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
[self.myTabelView scrollRectToVisible:activeField.frame animated:YES];
}
}
I now have the opposite problem. When the keyboard does show, towrad the top doesn't show, and it's not possible to scroll all the way up either.
Hi and did you try to use TPKeyboardAvoiding ? I use it to solve such cases without to need to code anything... You can try it as CocoaPod quickly.
I have a View embedded inside a Scroll View. I have written code such that when the cursor is placed in a text field (within the View) that is hidden by the keyboard that the screen will readjust such that the text field is no longer hidden. I am using autolayout to do this.
My problem is that when I put the View in the View Controller at the position I want it, there is a lot of additional white space above when I run the simulator. But when the keyboard comes up (and the screen redraws) then I can scroll up and the View Controller no longer has that additional white space.
If I adjust the view so that there isn't any white space (so it appears as on the storyboard) then when the keyboard appears, I cannot scroll to the top of the View.
I assume this has something to do with how the View is centered within the Scroll View but I have tried numerous adjustments on the constraints in the Size Inspector and cannot resolve this. I would really like to fix this in the storyboard (versus through code) if at all possible...
Here is the code:
- (void) keyboardDidShow:(NSNotification *)notification
{
NSDictionary* info = [notification userInfo];
CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
kbRect = [self.view convertRect:kbRect fromView:nil];
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbRect.size.height, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
CGRect aRect = self.view.frame;
aRect.size.height -= kbRect.size.height;
if (!CGRectContainsPoint(aRect, self.activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:self.activeField.frame animated:YES];
}
}
- (void) keyboardWillBeHidden:(NSNotification *)notification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
}
Turns out that I was setting the EdgeInsets value too high... when I changed from
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbRect.size.height, 0.0);
to
UIEdgeInsets contentInsets = UIEdgeInsetsMake(60.0, 0.0, kbRect.size.height, 0.0);
The positioning was improved.
I have a custom inherited UIView class with a UITableView within it as its only subview. I'm trying to mimic the normal functionality of the UITableViewController when the keyboard is shown to adjust the contentInset and scrollIndicatorInsets of the table view to the height of the keyboard. This is my method that gets called when the keyboard did show from within my custom UIView class:
- (void)keyboardDidShow:(NSNotification*)notification
{
NSDictionary* info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
_tableView.contentInset = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
_tableView.scrollIndicatorInsets = _tableView.contentInset;
}
This works to a certain extent, but there is still some overlap of the keyboard onto the table view for some reason by maybe ten or so pixels.
I'm thinking it has something to do with not taking into account some of the other screen geometry but I don't see how that could be. The height of the keyboard should be exactly what I need because the tableView stretches all the way to the bottom of the screen. Any ideas?
Change the tableView.frame.size.height, to account for the keyboard.
when keyboard is showing, reduce the height,
when not showing, increase the height.
refer to this if you want to consider the keyboard height for all possibilities http://www.idev101.com/code/User_Interface/sizes.html
Dont mess with the contentInset and the scrollIndicatorInsets. Just setting the frameSize will take care of these for you.
this is how your method should be
- (void)keyboardDidShow:(NSNotification*)notification
{
NSDictionary* info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
CGRect rect = _tableView.frame;
rect.size.height = _tableView.frame.size.height - kbSize.height;
_tableView.frame = rect;
}
- (void)keyboardWillHide:(NSNotification*)notification
{
NSDictionary* info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
CGRect rect = _tableView.frame;
rect.size.height = _tableView.frame.size.height + kbSize.height;
_tableView.frame = rect;
}
I have used this piece of code for a similar functionality. So if its still not working, there's something else going wrong.
I am curious why this isn't working for you, as I have basically the same thing and it is working for me. There is only one difference that I can see, in that I don't access '_tableView' and instead make sure that I'm always using the getter and setter.
Here is what I do, that is working.
- (void)keyboardDidShow:(NSNotification *)keyboardNotification
{
NSDictionary *info = [keyboardNotification userInfo];
CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
CGFloat newBottomInset = 0.0;
UIEdgeInsets contentInsets;
if (UIDeviceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]) ) {
newBottomInset = keyboardSize.height;
} else {
newBottomInset = keyboardSize.width;
}
contentInsets = UIEdgeInsetsMake(0.0, 0.0, newBottomInset, 0.0);
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
}
Note that my app allows device rotation and when that happens the value used needs to be the width of the keyboard because the values are relative to the portrait orientation, which caused me hours of confusion.
Hopefully the self.tableView access will make the difference.