I am having problem with the textfield input. In the 'CommentviewController' I have a scrollable tableview to display the previous comments, and at the bottom is a UItextField for the user to enter the comment and post it. The problem is: when I tried to type in the textfield and the keyboard is toggled, the text jumps up and down while I 'm typing. For example, the first char I typed is above the keyboard, and the second is below and behind the keyboard. Anybody has any idea about the cause? The test device is a 64 GB itouch5, and the code is written in objective C, and I am using the Xcode 6.3.2.
<i>`- (void)keyboardWasShown:(NSNotification*)aNotification {
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
theKBSize = kbSize;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height - 10, 0.0);
self.tvComment.contentInset = contentInsets; self.tvComment.scrollIndicatorInsets = contentInsets;
CGRect uvFrame = _uvComment.frame;
uvFrame.origin.y = self.view.frame.size.height - kbSize.height - _uvComment.frame.size.height; _uvComment.frame = uvFrame; } `</i>
<i> `- (void)keyboardWillBeHidden:(NSNotification*)aNotification {
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
_tvComment.contentInset = contentInsets;
_tvComment.scrollIndicatorInsets = contentInsets;
}`</i>
<i>`- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
if(string==nil || [string length]<1) {
[self.btnSend setEnabled: NO];
}else {
[self.btnSend setEnabled: YES];
}
return YES;
}`</i>
Are you changing the scroll position of the tableView?
A UITableView will automatically scroll so that the UITextField is not hidden by the keyboard when selected and the keyboard pops up. If you are changing the scroll position, that could be interfering with the auto scroll behavior.
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 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
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 an iPhone that I am adding landscape support. It was portrait only before.
I am having problems with getting text fields moved out of the way when the keyboard shows.
I am using a solution very similar to Apple's solution documented here.
The solution works just fine when in portrait mode but when I go to landscape mode it's not working at all. The view is not scrolling up but instead scrolls down.
I thought it may have to do with the keyboard hight/width and I think I am accounting for that properly.
Any advice to point out my stupidity or a much better solution is appreciated.
- (void)keyboardWillShow:(NSNotification *)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect activeFieldFrame = activeField.frame;
CGFloat kbHeight;
if (self.interfaceOrientation == UIInterfaceOrientationPortrait)
{
kbHeight = kbSize.height;
}
else
{
kbHeight = kbSize.width;
}
UIEdgeInsets contentInsets;
contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbHeight, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
CGRect aRect = self.view.frame;
aRect.size.height -= kbHeight;
activeFieldFrame.origin.y += scrollView.frame.origin.y+aRect.origin.y;
if (!CGRectContainsRect(aRect, activeFieldFrame) )
{
CGPoint scrollPoint = CGPointMake(0.0, activeFieldFrame.origin.y-kbHeight-aRect.origin.y);
[scrollView setContentOffset:scrollPoint animated:YES];
}
}
Note I am doing this in the keyboard WILL show as I think it looks better to move the view before the keyboard is shown.
OK, I'll answer my own question with my solution. Of course I seem to come across the solution right after I post to SO.
My maths were all wrong.
Here is my updated version in case it helps anyone else.
This will work both landscape and portrait.
- (void)keyboardWillShow:(NSNotification *)aNotification
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect activeFieldFrame = activeField.frame;
CGRect scrollViewFrame = scrollView.frame;//used so I can see values below while debugging
CGFloat kbHeight;
if (self.interfaceOrientation == UIInterfaceOrientationPortrait)
{
kbHeight = kbSize.height;
}
else
{
kbHeight = kbSize.width;
}
UIEdgeInsets contentInsets;
contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbHeight, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbHeight;
activeFieldFrame.origin.y += scrollViewFrame.origin.y+aRect.origin.y;
if (!CGRectContainsRect(aRect, activeFieldFrame) )
{
//add +5 here to give just a little room between field and keyboard
//subtracting scrollviewFrame.origin.y handles cases where scrollview is not at top (0,0) of the view
CGPoint scrollPoint = CGPointMake(0.0, activeFieldFrame.origin.y + activeFieldFrame.size.height + 5 - aRect.size.height - scrollViewFrame.origin.y);
[scrollView setContentOffset:scrollPoint animated:YES];
}
}
}
One interesting thing to note that I ran across is that if you register to get keyboard notifications on view A and pop modal view B over the top of view A and modal view B also needs keyboard shenanigans so you register modal view B to handle them, view A will still get the keyboard event and execute the code even though it is not visible on screen!
The original view A will still get the keyboard will show event if it's part of a tab-based design and another view C that has an edit field which is shown by another tab.
It seems logical that you should unregister listening for keyboard events when your view will disappear and register for events when your view will appear.
Hopefully this helps somebody else.
Scroll views are usually scrolled for you when your text field becomes first responder. I've had times where I haven't wanted this, so far the only workaround I have found was to wrap the text fields in scroll views that are the same size as the field so the auto scrolling behavior effects them and not my main scroll view.