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.
Related
I have a problem about the iOS at UIScrollview in Objective-C.
I drag the UI auto layout about below photo.
When I click the textfield, the keyboard will show, and I need can scroll the view.
It is seem is ok, but when I click done button and hide the keyboard,
I click textfield again, the keyboard will show, but I can't scroll the view again.
And other problem is like upper photo,
When I scrolled on the tableview , the tableview is can't scroll,
it is scroll the outside scroll view, how can I set the touch on the tableview , it's scroll tableview .
My keyboard event code below and I had upload this page complete code and auto layout project in GitHub:
this problem link
Have anyone can give me some help? thank you very much.
- (void)viewDidLoad {
[super viewDidLoad];
[self registerForKeyboardNotifications];
self.tf.inputAccessoryView = self.keyboardToolbarVw;
}
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
- (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.sv.contentInset = contentInsets;
self.sv.scrollIndicatorInsets = contentInsets;
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, self.view.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, self.view.frame.origin.y-kbSize.height);
[self.sv setContentOffset:scrollPoint animated:YES];
}
}
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.sv.contentInset = contentInsets;
self.sv.scrollIndicatorInsets = contentInsets;
}
- (IBAction)keyboardToolbarDoenBtnAction:(UIButton *)sender {
[self.tf resignFirstResponder];
}
After reviewing you code, it seems problem UIScrollView frames update in - (void)keyboardWasShown:(NSNotification*)aNotification
Instead of doing such manually work on frames, please try IQKeyboardManager
I’ll suggest to use IQKeyboardManager library in all our projects :) It’s a drop-in universal library which allows you to prevent issues of the keyboard sliding up and covering UITextField/UITextView without needing you to writing any code and much more…
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 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....
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 used code to make the screen scroll when the keyboard is covering up a textfield.
I have a list of textfields, and i started putting each inside of its own uiview for styling and organizational purposes.
now my code only works when i begin actually typing in the textfield. this is the monstrosity I copied from apple. Note: I added one parameter to
registerForKeyboardNotifications so that I could include this in a parent class and call it from anywhere
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications:(UIScrollView *)scroll
{
_scroller = scroll;
[[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
{
NSLog(#"hey");
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
_scroller.contentInset = contentInsets;
_scroller.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);
[_scroller setContentOffset:scrollPoint animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
_scroller.contentInset = contentInsets;
_scroller.scrollIndicatorInsets = contentInsets;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField{
_activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
_activeField = nil;
}
I have narrowed down the problem to this part in the viewcontroller
for (id subView in _tpnScroll.subviews)
{
if ([subView isKindOfClass:[UIView class]]) {
UIView *thisView = subView;
for(id textfield in thisView.subviews){
if([textfield isKindOfClass:[UITextField class]]){
[textfield setDelegate:self];
}
}
}
}
the original code was
for (id subView in _tpnScroll.subviews){
if ([subView isKindOfClass:[UITextField class]]) {
[subView setDelegate:self];
}
}
in the first example. im looping through my UIViews, and locating the UITextfields, and setting the delegate to self (this part I don't totally understand, still trying to understand the concept of a delegate)
in the second example, the textfields are located directly on the scrollview so i just loop through them directly.
sorry if this was wordy.
Try replacing keyboardWasShown with this.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSLog(#"hey");
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
_scroller.contentInset = contentInsets;
_scroller.scrollIndicatorInsets = contentInsets;
// the scroll view will only scroll if the text field is not fully visible
// no need to check if it is actually covered
[_scroller scrollRectToVisible:[_scroller convertRect:_activeField.bounds fromView:_activeField]
animated:YES];
}
Converting the text field's bounds to the scroll view's coordinate system makes sure that it works if the text field is inside the scroll view even if it is not directly inside it.