ViewA 顶部显示了一个子视图。请在下面找到屏幕布局。当选择UITextField时显示键盘时,即使它不与UITextField重叠,视图也会向上滚动。
ViewA
-> UIButton
subView
-> UIScrollView
-> UITextField
-> UITextField
ViewA
-----------
| |
| |
| Button |
| |
| |
-----------
subView
--------------
| |
| |
| UITextField |
| UITextField |
| |
--------------
我已注册键盘通知
- (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];
}
坐标系转换中有一个小错误:convertRect:toView:从接收器的坐标系转换为传递视图的坐标。
如果self.activeField.frame
是代码所暗示的self.scrollViewIb
坐标系中的一个矩形,那么转换应该是这样的......
CGRect frame = [self.scrollViewIb convertRect:self.activeField.frame toView:self.view];
请注意,我还建议将self.viewSelf.superview
更改为 self.view
。 如果此代码在包含所有这些子视图的视图控制器中运行,则 self.view 应该足够且正确。
我认为问题是你总是向上滚动,无论键盘是否与你的文本字段重叠。
您必须获取文本字段的框架,计算到屏幕底部的距离,并检查键盘高度(以及顶部可能的工具栏(是否与您的文本字段重叠,然后才向上滚动。
无论如何,我个人放弃了一次又一次地实现向上滚动行为。我现在改用IQKeyboardManager。只需将其作为 Pod 安装到您的项目中,并在应用程序中调用 IQKeyboardManager.sharedManager().enable = true
(didFinishLaunchingWithOptions(,您就可以设置好了。
您甚至可以免费获得带有下一个/上一个和完成按钮的工具栏。
当我们身处世界上拥有大量开放图书馆时,请不要担心。
通过将 KeyboardLib Lib 添加到代码中或由 pod 使用
。只需构建它。在每次打开键盘时,将显示"下一个"选项,带有"完成"按钮的"上一个"箭头。具有自动事件处理功能的零行代码。
也许这个将解决问题并改善应用程序的解决方案。
*Add this in your Controller or the other way is to create a category on UITextField. If you are creating a category on UITextfield just call below methods in delegate methods of 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];
}*