I have 10 textfields on tableview that tableview scrolling disabled.
How to handle keyboard avoiding textfields.
The Following is what I have tried with
// Register notification when the keyboard will be show
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardWillShowNotification
object:nil];
// Register notification when the keyboard will be hide
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification
object:nil];
pragma mark - keyboard notification (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);
guestRechargeTableView.contentInset = contentInsets;
guestRechargeTableView.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, activeField.frame.origin) )
{
[guestRechargeTableView scrollRectToVisible:activeField.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
guestRechargeTableView.contentInset = contentInsets;
guestRechargeTableView.scrollIndicatorInsets = contentInsets;
}
This is working but not proper when selecting on textfield and moves up.Provide solution for that or any other alternative answer..
Happy Coding....
Related
In my iOS app, there are almost 10 ViewControllers inside which UITextFields are present.
I implemented functionality of shifting content view upwards when keyboard appears.
https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html
This site explains all.
But my problem is that I have to repeat the same code inside every View Controller. Is their any way so that I can write common class or method which works with all my 10 ViewControllers, so that reusability in code can be achieved?
From the apple doc, I have to use following methods. But I am stuck at a place where I have to pass instance of scrollview and active text field (For each view controller, these instances are different) to my common class/method.
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// 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);
scrollView.contentInset = contentInsets;
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, activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:activeField.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
Create property in base view controller for scrollView and initialize it in viewDidLoad method of each derived view controllers. Also move activeField property to base view controller.
I am working with fully auto-layout.
Last UITextField (end of the view before done button): I set setContentOffset in textFieldDidBeginEditing, it works fine but when I try to scroll (at keyboard shown), UIScrollView is back to normal.
Then text field back to keyboard. Here my code at textFieldDidBeginEditing.
I am using bskeyboardcontroller for next and previous and done button.
[self.scrollviewDetail setContentOffset:CGPointMake(0, 500) animated:YES];
Problem is your Scroll view height on KeyBoard appearance in View, simply you change scroll insects or frame to avoid this problem, if scroll view content offset greater than (content size - scroll view frame size) while scroll it will reset automatically in Scroll view.
Try this code :
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)keyboardDidShow:(NSNotification *)notification {
CGRect keyboardRect = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardRect.size.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
CGRect aRect = self.view.frame;
aRect.size.height -= keyboardRect.size.height;
if (!CGRectContainsPoint(aRect, currentTextField.frame.origin) ) {
[scrollView scrollRectToVisible:currentTextField.frame animated:NO];
}
}
- (void)keyboardDidHide:(NSNotification *)notification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
I have a text box in a TableView and when the user selects a switch it appears ( becomes visible) and a keyboard pops up, and when the user turns off the switch the TextBox disappears and keyboard hides. During the time when the keyboard appears and disappears I want to shift the tableView slightly up and then back to original position. Here is the code
-(IBAction)actionSwitch:(id)sender
{
isSearchTerm = [switchSearchTerm isOn];
[self.tableView reloadData];
if(isSearchTerm == YES)
{
[txtSearchTerm becomeFirstResponder];
floatBottom = self.tableView.contentInset.bottom;
self.tableView.contentInset=UIEdgeInsetsMake(0,0,200,0);
[self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForSelectedRow] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
else
{
[txtSearchTerm resignFirstResponder];
self.tableView.contentInset=UIEdgeInsetsMake(0,0,floatBottom,0);
[self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForSelectedRow] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
}
The else part doesn't bring the tableview back to its original position, please help.
If your tableView lies in a navigation controller or the rootViewController of a navigation controller and you are doing all this on iOS7+ with UIViewController's property automaticallyAdjustsScrollViewInsets set to YES. You'd better handle the keyboard appear as the document suggested
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// 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);
scrollView.contentInset = contentInsets;
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, activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:activeField.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
There is another way to do this. Both can be found in "Moving Content That Is Located Under the Keyboard" "Text Programming Guide for iOS"
I solved this by setting the extend under top bar property to NO , under view controllers properties in Property inspector by selecting the ViewController.
I'm having a startview like this:
Where The first half of the screen is a Google map and the second half is a UITableview with in the header cell a UISearchbar.
When I click on the searchbar this happens on big screens but on small screens my uisearchbar is covered with the keyboard.
As you can see , when the keyboard shows up the searchbar moves a little bit to the bottom. I don't want that. It should push everything up so the Tableview is visible.
I followed a tutorial about contentInset. But it doesn't do anything.
- (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];
}
- (void)keyboardWillShow:(NSNotification *)notification
{
NSLog(#"KeyboardWillshow");
// Step 1: Get the size of the keyboard.
CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
// Step 2: Adjust the bottom content inset of your scroll view by the keyboard height.
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
// Step 3: Scroll the target text field into view.
CGRect aRect = self.view.frame;
aRect.size.height -= keyboardSize.height;
if (!CGRectContainsPoint(aRect, _searchBar.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, _searchBar.frame.origin.y - (keyboardSize.height-15));
[self.tableView setContentOffset:scrollPoint animated:YES];
NSLog(#"Scrolled");
}
}
- (void)keyboardWillHide:(NSNotification *)notification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.tableView.contentInset = contentInsets;
self.tableView.scrollIndicatorInsets = contentInsets;
}
It comes in the if test where Scrolled is printed. And still nothing happens.
Where _searchBar is my UISearchbar variable.
Anyone an idea?
EDIT:
Solved the problem except the UISearchbar jump crapy down when clicking on it. This creates a gap like you can see on the screenshot:
See the example below.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
float height =150;
float yPoint = aRect.size.height-height;
[self.tblSearch setFrame:CGRectMake(self.tblSearch.frame.origin.x
, yPoint, self.tblSearch.frame.size.width, height)];
}
If your searchbar, tableview and mapview is all place in a view,
and you want to push the tableview and searchbar visible when keyboardWillshow,
you should update frame instead of contentInset.
I am using UITableView, where each cell contains a UITextField, and using Apple official example, I wish to perform goal, moving the active field above the keyboard if it's already hidden. However, the form doesn't move although the UITableView is scroll eabled. Here is my relevant code, please help me pointing on what seems to be missing/wrong:
#interface ViewController (){
UITextField *activeField;
}
- (void)viewDidLoad
{
//....
objTableView.scrollEnabled=YES;
//....
}
#pragma mark - Keyboard notifications
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// 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);
objTableView.contentInset = contentInsets;
objTableView.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 -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
[objTableView setContentOffset:scrollPoint animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
objTableView.contentInset = contentInsets;
objTableView.scrollIndicatorInsets = contentInsets;
}
#pragma mark - UITextFieldDelegate protocol method
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
activeField = nil;
}
Try this code:
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
CGRect rc = [activeField bounds];
rc = [activeField convertRect:rc toView:objTableView];
[objTableView scrollRectToVisible:rc animated:YES];
}