In auto-layout scrollview setContentOffset not working correctly - ios

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;
}

Related

Write a common method for all view controllers to adjust frame of content view (of UIScrollView) when keyboard appears

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.

uitextfields with tableview keyboard avoiding when tableview scrolling disabled

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....

UIEdgeInsets not working exactly the same as expect

I've add a scrollView in the view controller and register keyboard show and hidden notifications
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationController.navigationBar.translucent = NO;
[self registerForKeyboardNotifications];
// add UITapGestureRecognizer
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
[scrollView addGestureRecognizer:tap];
scrollView.delegate = self;
[self setupAView];
}
- (void)setupAView {
// setting up aView...
scrollView.contentSize = CGSizeMake(self.view.frame.size.width, aView.frame.size.height);
-(void)dismissKeyboard {
[aView.aTextView resignFirstResponder];
}
- (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
{
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, aView.frame.size.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
CGPoint aPoint = CGPointMake(0, aView.frame.size.height);
[scrollView setContentOffset:aPoint animated:NO];
}
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
// scrollView insets
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
this works fine, when I tap aTextView and aView in scrollView will move above keyboard view, but meanwhile if I scrolled the scrollView, whole view will automatically drop down a bit, How come the action will change the insets value or the scrollView contentSize value?

UITableview doesn't scroll up when keyboard is shown

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.

How do I delay the iOS keyboard from popping up?

So...I have my UIScrollView move up when the keyboard pops up, and that works...except that they UIScrollView and the keyboard don't come up in sync...first, the keyboard pops up, then the UIScrollView.
I know there's a way to delay the keyboard so that it shows up at the same time that the view scrolls up; how do I do that?? I tried this in viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
...and I have this as well:
- (void)keyboardWillShow:(NSNotification *)notification
{
[NSTimer scheduledTimerWithTimeInterval:4000 target:self selector:#selector(keyboardWillShow:) userInfo:nil repeats:NO];
}
(I know, 4000 is a huge number, but I wanted to make sure there was a delay!!)
Also, when I dismiss the keyboard, rather than a smooth scroll, the UIScrollView just plain jumps back into place instead of easing down...is there a reasonable way to take care of that?
UPDATE:
Got it...thanks to Steven Fisher for helping me on the right path...I moved everything to keyboardWillShow, and added the following code:
[UIScrollView beginAnimations:nil context:NULL];
[UIScrollView setAnimationDelegate:self];
[UIScrollView setAnimationDuration:.32];
[UIScrollView setAnimationBeginsFromCurrentState:NO];
Somehow this also solved my "jump" problem when the keyboard goes away! woohoo!
This is the code that apple documentation given for this kind situation.
// 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 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);
[scrollView setContentOffset:scrollPoint animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardWillHideNotification
object:nil];
}
- (void)keyboardWasShown:(NSNotification *)notification
{
// To avoid keyboard hides the view
CGRect frame = self.view.bounds;
if (capitalTextField.enabled ==YES)
{
if ([notification name]== UIKeyboardDidShowNotification )
{
frame.origin.y += 200;
[self.scrollView scrollRectToVisible:frame animated:YES];
}
else
{
frame.origin.y -= 200;
[self.scrollView scrollRectToVisible:frame animated:YES];
}
}
}
the below code will delay pop up
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3f];
[textField becomefirstresponder];
[UIView commitAnimations];

Resources