There is a subView presented on top of ViewA. Please find the screen layout below. When keyboard is shown on selecting UITextField even if its not overlapping with UITextField the view is scrolled up.
ViewA -> UIButton subView -> UIScrollView -> UITextField -> UITextField ViewA ----------- | | | | | Button | | | | | ----------- subView -------------- | | | | | UITextField | | UITextField | | | --------------
I have registered keyboard notification
- (void) viewWillAppear:(BOOL)animated { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } - (void) keyboardDidShow:(NSNotification *)notification { NSDictionary* info = [notification userInfo]; CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]; UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbRect.size.height, 0.0); self.scrollViewIb.contentInset = contentInsets; self.scrollViewIb.scrollIndicatorInsets = contentInsets; CGRect aRect = self.viewSelf.frame; aRect.size.height -= kbRect.size.height; CGRect frame = [self.viewSelf convertRect:self.activeField.frame toView:self.viewSelf.superview]; if (!CGRectContainsPoint(aRect, frame.origin) ) { [self.scrollViewIb scrollRectToVisible:self.activeField.frame animated:YES]; } } - (void) keyboardWillBeHidden:(NSNotification *)notification { self.scrollViewIb.scrollEnabled = true; UIEdgeInsets contentInsets = UIEdgeInsetsZero; self.scrollViewIb.scrollIndicatorInsets = contentInsets; [self.scrollViewIb setContentOffset:CGPointZero animated:false]; }
4 Answers
Answers 1
There's a minor mistake in the coordinate system conversion: convertRect:toView: converts from the coordinate system of the receiver to the coordinates of the passed view.
If self.activeField.frame
is a rectangle in the coordinate system of self.scrollViewIb
as the code implies, then the conversion should go like this...
CGRect frame = [self.scrollViewIb convertRect:self.activeField.frame toView:self.view];
Notice that I also suggest changing self.viewSelf.superview
to self.view
. If this code is running in the view controller that contains all of these subviews, then self.view should be sufficient and correct.
Answers 2
I think the problem is that you are always scrolling up, no matter if the keyboard overlaps your textfield or not.
You would have to get the frame of the textfield, calculate the distance to the bottom of the screen and check if the keyboard height (plus possible toolbar on top of it) would overlap your textfield and only then scroll up.
Anyways, I personally gave up on implementing scroll up behavior again and again. I now switched to using IQKeyboardManager. Simply install it as a Pod in your project and call IQKeyboardManager.sharedManager().enable = true
in application(didFinishLaunchingWithOptions) and you are all set.
You even get a toolbar with next/previous and done button for free.
Answers 3
Don't get worry when we are in the world with the lots of open libraries.
Use KeyboardLib Lib by adding it to code or by the pod.
Just build it. On every Keyboard open that will show option for the Next, previous arrow with the Done button. Zero line of code with automatic event handling.
May be this one will solve the issue and a solution for the app betterment.
Answers 4
Add this in your Controller or the other way is to create a category on UITextField static CGFloat const MINIMUM_SCROLL_FRACTION = 0.4; static CGFloat const MAXIMUM_SCROLL_FRACTION = 0.8; static CGFloat const PORTRAIT_KEYBOARD_HEIGHT = 185; static CGFloat const PORTRAIT_KEYBOARD_HEIGHT1 = 230; static CGFloat const LANDSCAPE_KEYBOARD_HEIGHT = 140; static CGFloat const KEYBOARD_ANIMATION_DURATION = 0.3;` - (void)textFieldDidBeginEditing:(UITextField *)textField view:(UIView *)view{CGRect textFieldRect = [view.window convertRect:textField.bounds fromView:textField];CGRect viewRect = [view.window convertRect:view.bounds fromView:view];CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height;CGFloat numerator = midline - viewRect.origin.y - MINIMUM_SCROLL_FRACTION * viewRect.size.height;CGFloat denominator = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION) * viewRect.size.height; CGFloat heightFraction = numerator / denominator; if (heightFraction < 0.0) { heightFraction = 0.0; } else if (heightFraction > 1.0) { heightFraction = 1.0; } UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; if([[ UIScreen mainScreen ] bounds ].size.height == 568) { if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) { animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction); } else { animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction); } } else{ if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) { animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction + 23); } else { animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction + 23); } } CGRect viewFrame = view.frame; viewFrame.origin.y -= animatedDistance; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION]; [view setFrame:viewFrame]; [UIView commitAnimations]; } - (void)textFieldDidEndEditing:(UITextField *)textField view:(UIView *)view CGRect viewFrame = view.frame; viewFrame.origin.y += animatedDistance; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCur rentState:YES]; [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION]; [view setFrame:viewFrame]; [UIView commitAnimations]; }
0 comments:
Post a Comment