键盘重叠时向上移动UITextField

时间:2017-05-22 18:54:17

标签: ios objective-c iphone uiscrollview autolayout

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

}

4 个答案:

答案 0 :(得分:5)

坐标系转换中存在一个小错误:convertRect:toView:从接收器的坐标系转换为传递视图的坐标。

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

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

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

答案 1 :(得分:2)

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

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

无论如何,我个人放弃了一次又一次地实现向上滚动的行为。我现在切换到使用IQKeyboardManager。只需在项目中将其作为Pod安装,然后在应用程序中调用IQKeyboardManager.sharedManager().enable = true(didFinishLaunchingWithOptions)即可完成设置。

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

答案 2 :(得分:2)

当我们身处大量开放式图书馆时,不要担心。

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

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

可能是这个将解决问题并为app改进的解决方案。

答案 3 :(得分:2)

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