UIScrollView Content tabs do not work for keyboard height

I am trying to move a UIScrollView when the keyboard hides a UITextField by contentInsets using contentInsets as shown.

However, it does not work for keyboard height. The height of the keyboard is 216, but it only stops scrolling in the right place if I set the bottom insert to 515 for iPhone portrait mode and 310 for iPhone landscape mode. Why would these measurements be so different? I do not want to hard code these arbitrary values.

 - (void)viewDidLoad { [super viewDidLoad]; self.view.frame = self.parentViewController.view.frame; [self.textView becomeFirstResponder]; NSLog(@"scrollview: %f,%f, parent: %f,%f", self.view.frame.size.height, self.view.frame.size.width, self.parentViewController.view.frame.size.height, self.parentViewController.view.frame.size.width); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } - (void)keyboardWasShown:(NSNotification *)notification { if([[UIDevice currentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone) { // Step 1: Get the size of the keyboard. CGFloat keyboardHeight = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height; // Step 2: Adjust the bottom content inset of your scroll view by the keyboard height. UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardHeight, 0.0); ((UIScrollView*)self.view).contentInset = contentInsets; ((UIScrollView*)self.view).scrollIndicatorInsets = contentInsets; // Step 3: Scroll the target text field into view. CGRect aRect = self.view.frame; aRect.size.height = aRect.size.height - keyboardHeight; if (!CGRectContainsPoint(aRect, self.textView.frame.origin) ) { CGPoint scrollPoint = CGPointMake(0.0, self.textView.frame.origin.y - keyboardHeight); [((UIScrollView*)self.view) setContentOffset:scrollPoint animated:YES]; } } } - (void) keyboardWillHide:(NSNotification *)notification { UIEdgeInsets contentInsets = UIEdgeInsetsZero; ((UIScrollView*)self.view).contentInset = contentInsets; ((UIScrollView*)self.view).scrollIndicatorInsets = contentInsets; } 

Edit:

Before opening the keyboard, I will print this:

 NSLog(@"scrollview: %f,%f, parent: %f,%f", self.view.frame.size.height, self.view.frame.size.width, self.parentViewController.view.frame.size.height, self.parentViewController.view.frame.size.width); 

and he prints this:

 scrollview: 431.000000,320.000000, parent: 431.000000,320.000000 
+6
source share
2 answers

I think the main problem is that you need to use UIKeyboardFrameEndUserInfoKey instead of UIKeyboardFrameBeginUserInfoKey .

At the same time, I wrote another version of this method that will work even if the scroll is not placed at the bottom of the screen and may work better for you:

Note that instead of self.textField I use self.activeTextField .

 // Called when the UIKeyboardDidShowNotification is sent. - (void)keyboardWasShown:(NSNotification*)aNotification { // Calculate the frame of the scrollview, in self.view coordinate system UIScrollView *scrollView = self.scrollView; CGRect scrollViewRect = [self.view convertRect:scrollView.frame fromView:scrollView.superview]; // Calculate the frame of the keyboard, in self.view coordinate system NSDictionary* info = [aNotification userInfo]; CGRect kbRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; kbRect = [self.view convertRect:kbRect fromView:nil]; // Figure out where the two frames overlap, and set the content offset of the scrollview appropriately CGRect hiddenScrollViewRect = CGRectIntersection(scrollViewRect, kbRect); if (!CGRectIsNull(hiddenScrollViewRect)) { UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, hiddenScrollViewRect.size.height, 0.0); scrollView.contentInset = contentInsets; scrollView.scrollIndicatorInsets = contentInsets; } [self scrollToActiveTextField]; } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { self.scrollView.contentInset = UIEdgeInsetsZero; self.scrollView.scrollIndicatorInsets = UIEdgeInsetsZero; } - (void)scrollToActiveTextField { if (self.activeTextField) { CGRect visibleRect = self.activeTextField.frame; visibleRect = [self.scrollView convertRect:visibleRect fromView:self.activeTextField.superview]; visibleRect = CGRectInset(visibleRect, 0.0f, -5.0f); [self.scrollView scrollRectToVisible:visibleRect animated:YES]; } } 
+22
source

set the delegate of your scrollView as an independent circle in which you split the scrollview in your code

  ((UIScrollView*)self.view).delegate=self; 

then

 - (void)viewDidLoad { [super viewDidLoad]; self.view.frame = self.parentViewController.view.frame; [self.textView becomeFirstResponder]; NSLog(@"scrollview: %f,%f, parent: %f,%f", self.view.frame.size.height, self.view.frame.size.width, self.parentViewController.view.frame.size.height, self.parentViewController.view.frame.size.width); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } - (void)keyboardWasShown:(NSNotification *)notification { if([[UIDevice currentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone) { // Step 1: Get the size of the keyboard. CGFloat keyboardHeight = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height; // Step 2: Adjust the bottom content inset of your scroll view by the keyboard height. UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardHeight, 0.0); ((UIScrollView*)self.view).contentInset = contentInsets; ((UIScrollView*)self.view).scrollIndicatorInsets = contentInsets; ((UIScrollView*)self.view).scrollEnabled=YES; } } - (void) keyboardWillHide:(NSNotification *)notification { UIEdgeInsets contentInsets = UIEdgeInsetsZero; ((UIScrollView*)self.view).contentInset = contentInsets; ((UIScrollView*)self.view).scrollIndicatorInsets = contentInsets; [((UIScrollView*)self.view) setContentOffset:CGPointMake(0.0f, 0.0f) animated:TRUE]; ((UIScrollView*)self.view).contentSize = CGSizeMake(((UIScrollView*)self.view).contentSize.width, ((UIScrollView*)self.view).contentSize.height); ((UIScrollView*)self.view).scrollEnabled=NO; } #pragma mark - set scrollView content position -(void)scrollViewToCenterOfScreen:(UIView *)theView { CGFloat theViewY = theView.center.y; CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame]; CGFloat avaliableHeight = applicationFrame.size.height - 300; CGFloat y = theViewY - avaliableHeight / 2.0; if(y<0) y = 0; [((UIScrollView*)self.view) setContentOffset:CGPointMake(0,y) animated:YES]; } #pragma -mark UITextField Delegate methods - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { [self scrollViewToCenterOfScreen:textField]; return YES; } 

Now set the delegate of your text box. Whenever textFieldShouldBeginEditing: your scrollview automatically jumps to this. scrollViewToCenterOfScreen: method sets the scroll position in the text position.

It definitely sets your insertions to scrollview content as well as setContentOffset. Please let me know if you are still experiencing this issue. Thanks

0
source

Source: https://habr.com/ru/post/945646/


All Articles