键盘重叠时向上移动 UITextField

Posted

技术标签:

【中文标题】键盘重叠时向上移动 UITextField【英文标题】:Move UITextField up when keyboard is overlapped 【发布时间】:2017-05-22 18:54:16 【问题描述】:

在 ViewA 上显示了一个 subView。请在下面找到屏幕布局。当键盘显示在选择 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];


【问题讨论】:

最好使用这个库github.com/michaeltyson/TPKeyboardAvoiding它会在键盘弹出时自动管理你的视图。 【参考方案1】:

坐标系转换有个小错误:convertRect:toView:从receiver的坐标系转换为传递的view的坐标。

如果self.activeField.frameself.scrollViewIb 坐标系中的一个矩形,正如代码所示,那么转换应该是这样的......

    CGRect frame = [self.scrollViewIb convertRect:self.activeField.frame toView:self.view];

请注意,我还建议将 self.viewSelf.superview 更改为 self.view。如果这段代码在包含所有这些子视图的视图控制器中运行,那么 self.view 应该是足够且正确的。

【讨论】:

建议的更改我仍然面临问题 嗯。很抱歉听到。我将在今天晚些时候自己构建这个,让你知道我出现了什么。同时,您可以记录所有视图的框架并将它们发布到这里吗?按钮、子视图、滚动视图及其两个文本视图? 请找项目github.com/dssandeep/ScrollTextField.git 嗯。不能运行它。我得到“无效的论点”。必须是构建设置中的某些内容。此外,超级不寻常和复杂的设置。您是否只是想在主视图上弹出“viewself”(带有两个文本字段)?推荐的方法是使用另一个视图控制器。 viewself 中还有一些 UI 元素。【参考方案2】:

我认为问题在于您总是向上滚动,无论键盘是否与您的文本字段重叠。

您必须获取文本字段的框架,计算到屏幕底部的距离并检查键盘高度(加上其顶部可能的工具栏)是否会与您的文本字段重叠,然后才能向上滚动。

无论如何,我个人一次又一次地放弃了实现向上滚动的行为。我现在改用 IQKeyboardManager。只需将其作为 Pod 安装在您的项目中,然后在 application(didFinishLaunchingWithOptions) 中调用 IQKeyboardManager.sharedManager().enable = true 即可。

您甚至可以免费获得带有下一个/上一个和完成按钮的工具栏。

【讨论】:

【参考方案3】:

当我们身处拥有大量开放图书馆的世界时,请不要担心。

通过将KeyboardLib Lib 添加到代码或通过 pod 来使用它。

只需构建它。在每次打开键盘时,都会显示带有完成按钮的下一个、上一个箭头的选项。 零代码行,具有自动事件处理功能。

这可能是解决问题和改进应用程序的解决方案。

【讨论】:

【参考方案4】:
*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];
                    *

【讨论】:

以上是关于键盘重叠时向上移动 UITextField的主要内容,如果未能解决你的问题,请参考以下文章

键盘存在时 UIViewController 向上移动

键盘出现多次时,滚动视图不会向上移动

显示软键盘时向上移动布局?

出现键盘时向上移动 UIView

出现软键盘时工具栏向上移动

Swift 防止 TabBar 在键盘处于活动状态时向上移动