【问题标题】:How do I scroll the UIScrollView when the keyboard appears?键盘出现时如何滚动 UIScrollView?
【发布时间】:2012-10-21 03:08:24
【问题描述】:

我的代码有问题。当我编辑应该被键盘弹出隐藏的UITextField 时,我正在尝试移动UIScrollView

我现在正在移动主框架,因为我不知道如何在代码中“向上滚动”。 所以,我做了一些代码,它工作正常,但是当我编辑一个 UItextfield 并切换到另一个 UITextField 而不按“返回”按钮时,主视图会变得很远。

我用我的变量大小、距离和 textFieldRect.origin.y 做了一个NSLog(),如下所示。当我将两个 UITextField 放在同一个位置(y 原点)并执行此特定的“开关”(不按回车键)时,我得到相同的数字,而我的代码在第一个 UITextField 编辑时工作正常,但不适用于第二次编辑。

看看这个:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
{
    int size;
    CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
    size = textFieldRect.origin.y + textFieldRect.size.height;
    if (change == FALSE)
    {
        size = size - distance;
    }
    if (size < PORTRAIT_KEYBOARD_HEIGHT)
    {
        distance = 0;
    }
    else if (size > PORTRAIT_KEYBOARD_HEIGHT)
    {
        distance = size - PORTRAIT_KEYBOARD_HEIGHT + 5; // +5 px for more visibility
    }
    NSLog(@"origin %f", textFieldRect.origin.y);
    NSLog(@"size %d", size);
    NSLog(@"distance %d", distance);
    CGRect viewFrame = self.view.frame;
    viewFrame.origin.y -= distance;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
    change = FALSE;
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    change = TRUE;
    CGRect viewFrame = self.view.frame;
    viewFrame.origin.y += distance;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
}

有什么想法吗?

【问题讨论】:

    标签: ios objective-c iphone cocoa-touch scrollview


    【解决方案1】:

    Apple 推荐的方法是更改​​UIScrollViewcontentInset。这是一个非常优雅的解决方案,因为您不必弄乱contentSize。 以下代码是从Keyboard Programming Guide 复制的,其中解释了此问题的处理。你应该看看它。

    // Call this method somewhere in your view controller setup code.
    - (void)registerForKeyboardNotifications
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                selector:@selector(keyboardWasShown:)
                name:UIKeyboardDidShowNotification object:nil];
       [[NSNotificationCenter defaultCenter] addObserver:self
                 selector:@selector(keyboardWillBeHidden:)
                 name:UIKeyboardWillHideNotification object:nil];
    }
    
    // Called when the UIKeyboardDidShowNotification is sent.
    - (void)keyboardWasShown:(NSNotification*)aNotification
    {
        NSDictionary* info = [aNotification userInfo];
        CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    
        // If active text field is hidden by keyboard, scroll it so it's visible
        // Your application might not need or want this behavior.
        CGRect aRect = self.view.frame;
        aRect.size.height -= kbSize.height;
        if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
            CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
            [scrollView setContentOffset:scrollPoint animated:YES];
        }
    }
    
    // Called when the UIKeyboardWillHideNotification is sent    
    - (void)keyboardWillBeHidden:(NSNotification*)aNotification
    {
        UIEdgeInsets contentInsets = UIEdgeInsetsZero;
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }
    

    Swift 版本:

    func registerForKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardAppear(_:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDisappear(_:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
    }
    
    // Don't forget to unregister when done
    deinit {
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidHide, object: nil)
    }
    
    @objc func onKeyboardAppear(_ notification: NSNotification) {
        let info = notification.userInfo!
        let rect: CGRect = info[UIKeyboardFrameBeginUserInfoKey] as! CGRect
        let kbSize = rect.size
    
        let insets = UIEdgeInsetsMake(0, 0, kbSize.height, 0)
        scrollView.contentInset = insets
        scrollView.scrollIndicatorInsets = insets
    
        // If active text field is hidden by keyboard, scroll it so it's visible
        // Your application might not need or want this behavior.
        var aRect = self.view.frame;
        aRect.size.height -= kbSize.height;
    
        let activeField: UITextField? = [addressTextView, servicePathTextView, usernameTextView, passwordTextView].first { $0.isFirstResponder }
        if let activeField = activeField {
            if !aRect.contains(activeField.frame.origin) {
                let scrollPoint = CGPoint(x: 0, y: activeField.frame.origin.y-kbSize.height)
                scrollView.setContentOffset(scrollPoint, animated: true)
            }
        }
    }
    
    @objc func onKeyboardDisappear(_ notification: NSNotification) {
        scrollView.contentInset = UIEdgeInsets.zero
        scrollView.scrollIndicatorInsets = UIEdgeInsets.zero
    }
    

    【讨论】:

    • 啊,好的。对不起,我没有明白你在谈论滚动部分。是的,activeField 只是 UITextField 属性的占位符。所以替换它并再试一次。您不需要更改大小,否则 textField 的高度会变大。
    • 您实际上并不想覆盖现有的 contentInsets.top,如果这样做,您的视图可能会滑到 Navigation 后面。
    • github.com/michaeltyson/TPKeyboardAvoiding 这是超级简单的解决方案
    • 最好将activeField.frame 转换为相对框架,因为activeField 不必是self.view 的直接子级。更新后的代码应类似于:CGRect aRect = self.view.frame; aRect.size.height -= kbSize.height; CGRect relativeFieldFrame = [activeField convertRect:activeField.frame toView:self.view]; if (!CGRectContainsPoint(aRect, relativeFieldFrame.origin) ) { CGPoint scrollPoint = CGPointMake(0.0, relativeFieldFrame.origin.y-kbSize.height); [self.mainView.scrollView setContentOffset:scrollPoint animated:YES]; }
    • 我不得不在 iOS 11 上使用 UIKeyboardFrameEndUserInfoKey 键,因为 UIKeyboardFrameBeginUserInfoKey 通常会给我一个零高度。
    【解决方案2】:

    我刚刚在 Xcode 7(beta 6)上使用适用于 iOS9 的 Swift 2.0 实现了这一点,在这里可以正常工作。

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        registerKeyboardNotifications()
    }
    
    func registerKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
    }
    
    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
    func keyboardWillShow(notification: NSNotification) {
        let userInfo: NSDictionary = notification.userInfo!
        let keyboardSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue.size
        let contentInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
        scrollView.contentInset = contentInsets
        scrollView.scrollIndicatorInsets = contentInsets
    
        var viewRect = view.frame
        viewRect.size.height -= keyboardSize.height
        if CGRectContainsPoint(viewRect, textField.frame.origin) {
            let scrollPoint = CGPointMake(0, textField.frame.origin.y - keyboardSize.height)
            scrollView.setContentOffset(scrollPoint, animated: true)
        }
    }
    
    func keyboardWillHide(notification: NSNotification) {
        scrollView.contentInset = UIEdgeInsetsZero
        scrollView.scrollIndicatorInsets = UIEdgeInsetsZero
    }
    

    为 Swift 3 编辑

    似乎您只需要使用 Swift 3 设置 contentInsetscrollIndicatorInset,滚动/contentOffset 会自动完成..

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        registerKeyboardNotifications()
    }
    
    func registerKeyboardNotifications() {
        NotificationCenter.default.addObserver(self,
                                             selector: #selector(keyboardWillShow(notification:)),
                                             name: NSNotification.Name.UIKeyboardWillShow,
                                             object: nil)
        NotificationCenter.default.addObserver(self,
                                             selector: #selector(keyboardWillHide(notification:)),
                                             name: NSNotification.Name.UIKeyboardWillHide,
                                             object: nil)
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    func keyboardWillShow(notification: NSNotification) {
        let userInfo: NSDictionary = notification.userInfo! as NSDictionary
        let keyboardInfo = userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue
        let keyboardSize = keyboardInfo.cgRectValue.size
        let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
        scrollView.contentInset = contentInsets
        scrollView.scrollIndicatorInsets = contentInsets
    }
    
    func keyboardWillHide(notification: NSNotification) {
        scrollView.contentInset = .zero
        scrollView.scrollIndicatorInsets = .zero
    }
    

    【讨论】:

    • 您能解释一下您的代码吗?我有两个文本字段,一旦我编辑第一个文本字段,它会向下滚动,而第二个文本字段会向上滚动。
    • 在 iPad 上,这会将滚动视图向下而不是向上移动。知道那里发生了什么吗?
    • @can 引用的 textField 是您根据当前第一响应者为视图控制器设置的变量
    • 我想知道为什么 Apple 现在会主动为我们滚动键盘上方的活动文本字段。
    • 在swift 4中将@objc放在keyboardWillShow和keyboardWillHide方法上
    【解决方案3】:

    Swift 5解决方案:

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        registerKeyboardNotifications()
    }
    
    func registerKeyboardNotifications() {
        NotificationCenter.default.addObserver(self,
                                             selector: #selector(keyboardWillShow(notification:)),
                                             name: UIResponder.keyboardWillShowNotification,
                                             object: nil)
        NotificationCenter.default.addObserver(self,
                                             selector: #selector(keyboardWillHide(notification:)),
                                             name: UIResponder.keyboardWillHideNotification,
                                             object: nil)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        NotificationCenter.default.removeObserver(self)
    }
    
    @objc func keyboardWillShow(notification: NSNotification) {
        let userInfo: NSDictionary = notification.userInfo! as NSDictionary
        let keyboardInfo = userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue
        let keyboardSize = keyboardInfo.cgRectValue.size
        let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
        scrollView.contentInset = contentInsets
        scrollView.scrollIndicatorInsets = contentInsets
    }
    
    @objc func keyboardWillHide(notification: NSNotification) {
        scrollView.contentInset = .zero
        scrollView.scrollIndicatorInsets = .zero
    }
    

    【讨论】:

    • 大部分工作,只需将UIKeyboardFrameBeginUserInfoKey更改为UIKeyboardFrameEndUserInfoKey
    • 我在 UITableView 中应用了这段代码。但是 TableView 不会立即向上滚动。
    • UIKeyboardWillShowUIKeyboardWillHideUIKeyboardFrameBeginUserInfoKey 已重命名为 UIResponder.keyboardWillShowNotificationUIResponder.keyboardWillHideNotificationUIResponder.keyboardFrameBeginUserInfoKey
    【解决方案4】:

    这里的所有答案似乎都忘记了景观的可能性。如果您希望设备旋转到横向视图时也能正常工作,那么您将面临问题。

    这里的诀窍是,虽然视图知道方向,但键盘不知道。这意味着在横向中,键盘的宽度实际上就是它的高度,反之亦然。

    要修改 Apple 推荐的更改内容插入的方式并使其支持横向,我建议使用以下方法:

    // Call this method somewhere in your view controller setup code.
    - (void)registerForKeyboardNotifications
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                selector:@selector(keyboardWasShown:)
                name:UIKeyboardDidShowNotification object:nil];
       [[NSNotificationCenter defaultCenter] addObserver:self
                 selector:@selector(keyboardWillBeHidden:)
                 name:UIKeyboardWillHideNotification object:nil];
    }
    
    // Called when the UIKeyboardDidShowNotification is sent.
    - (void)keyboardWasShown:(NSNotification*)aNotification
    {
        UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
        CGSize keyboardSize = [[[notif userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
        if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight ) {
            CGSize origKeySize = keyboardSize;
            keyboardSize.height = origKeySize.width;
            keyboardSize.width = origKeySize.height;
        }
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0);
        scroller.contentInset = contentInsets;
        scroller.scrollIndicatorInsets = contentInsets;
    
        // If active text field is hidden by keyboard, scroll it so it's visible
        // Your application might not need or want this behavior.
        CGRect rect = scroller.frame;
        rect.size.height -= keyboardSize.height;
        NSLog(@"Rect Size Height: %f", rect.size.height);
    
        if (!CGRectContainsPoint(rect, activeField.frame.origin)) {
            CGPoint point = CGPointMake(0, activeField.frame.origin.y - keyboardSize.height);
            NSLog(@"Point Height: %f", point.y);
            [scroller setContentOffset:point animated:YES];
        }
    }
    
    // Called when the UIKeyboardWillHideNotification is sent    
    - (void)keyboardWillBeHidden:(NSNotification*)aNotification
    {
        UIEdgeInsets contentInsets = UIEdgeInsetsZero;
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }
    

    这里要注意的部分如下:

    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGSize keyboardSize = [[[notif userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight ) {
        CGSize origKeySize = keyboardSize;
        keyboardSize.height = origKeySize.width;
        keyboardSize.width = origKeySize.height;
    }
    

    它的作用是检测设备的方向。如果是横向,它将“交换”keyboardSize 变量的宽度和高度值,以确保在每个方向上使用正确的值。

    【讨论】:

    • 好吧,如果滚动条占据屏幕的整个高度 UIEdgeInsetsMake(0.0, 0.0, kbSize.高度 - ([UIScreen mainScreen].bounds.size.height - cvf.origin.y - cvf.size.height), 0.0);其中 cvf 是 scroller.frame
    • if (orientation == UIInterfaceOrientationLandscapeLeft ||orientation == UIInterfaceOrientationLandscapeRight)
    【解决方案5】:

    对于这些东西不需要大量的编码,就像下面的代码一样简单:-

    您在 UIScrollview 中的所有文本文件都来自 nib,如下图所示:-

    YourViewController.h

    @interface cntrInquiryViewController : UIViewController<UIScrollViewDelegate,UITextFieldDelegate>
    {
         IBOutlet UITextField *txtName;
         IBOutlet UITextField *txtEmail;
         IBOutlet UIScrollView *srcScrollView;
    }
    @end
    

    从 nib 连接 IBOutlet,并从 NIB 连接 UItextfiled 的每个委托和 scrollview 委托

    -(void)viewWillAppear:(BOOL)animated
    {
        srcScrollView.contentSize = CGSizeMake(320, 500);
    
        [super viewWillAppear:YES];
    }
    
    
    -(void)textFieldDidBeginEditing:(FMTextField *)textField
    {
        [srcScrollView setContentOffset:CGPointMake(0,textField.center.y-140) animated:YES];//you can set your  y cordinate as your req also
    }
    
    -(BOOL)textFieldShouldReturn:(UITextField *)textField
    {
         [textField resignFirstResponder];
         [srcScrollView setContentOffset:CGPointMake(0,0) animated:YES];
    
    
        return YES;
    }
    

    注意如果没有连接文本文件的委托,那么没有一种方法可以工作,请确保所有 iBOulate 和委托都正确连接

    【讨论】:

    • 这是一种非常古老的方法,不应该使用。它依赖于不再相关的硬编码值和假设。
    • @Womble 有很多旧的但与当时的问题相关的答案(当问题被提出时)。所以,不要无故投反对票。
    【解决方案6】:

    Apple 的建议在 Swift 中重新编码 + 在 iOS 中使用 UIScrollView 和自动布局(基于以下链接:link 1link 2link 3):

    import UIKit
    
    class ViewController: UIViewController, UITextFieldDelegate {
    
        @IBOutlet var t1: UITextField!
        @IBOutlet var t2: UITextField!
        @IBOutlet var t3: UITextField!
        @IBOutlet var t4: UITextField!
    
        @IBOutlet var srcScrollView: UIScrollView!
    
        @IBOutlet var contentView: UIView!
    
        var contentViewCoordinates: CGPoint!
    
        override func viewDidLoad() {
    
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            /* Constraints on content view */
            let leftConstraint = NSLayoutConstraint(item:self.contentView,
                attribute:NSLayoutAttribute.Leading,
                relatedBy:NSLayoutRelation.Equal,
                toItem:self.view,
                attribute:NSLayoutAttribute.Left,
                multiplier:1.0,
                constant:0)
            self.view.addConstraint(leftConstraint)
    
            let rightConstraint = NSLayoutConstraint(item:self.contentView,
                attribute:NSLayoutAttribute.Trailing,
                relatedBy:NSLayoutRelation.Equal,
                toItem:self.view,
                attribute:NSLayoutAttribute.Right,
                multiplier:1.0,
                constant:0)
            self.view.addConstraint(rightConstraint)
    
            /* Tap gesture */
            let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "hideKeyboard")
            // prevents the scroll view from swallowing up the touch event of child buttons
            tapGesture.cancelsTouchesInView = false
            srcScrollView.addGestureRecognizer(tapGesture)
    
            /* Save content view coordinates */
            contentViewCoordinates = contentView.frame.origin
        }
    
        func hideKeyboard() {
            t1.resignFirstResponder()
            t2.resignFirstResponder()
            t3.resignFirstResponder()
            t4.resignFirstResponder()
        }
    
        var activeField: UITextField?
    
        func textFieldDidBeginEditing(textField: UITextField) {
            activeField = textField
        }
    
        func textFieldDidEndEditing(textField: UITextField) {
            activeField = nil
        }
    
        override func viewWillAppear(animated: Bool) {
            super.viewWillAppear(animated)
            let center = NSNotificationCenter.defaultCenter()
            center.addObserver(self, selector: "keyboardOnScreen:", name: UIKeyboardDidShowNotification, object: nil)
            center.addObserver(self, selector: "keyboardOffScreen:", name: UIKeyboardDidHideNotification, object: nil)
        }
    
        func keyboardOnScreen(notification: NSNotification){
            // Retrieve the size and top margin (inset is the fancy word used by Apple) 
            // of the keyboard displayed.
            let info: NSDictionary  = notification.userInfo!
            let kbSize = info.valueForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue().size
            let contentInsets: UIEdgeInsets  = UIEdgeInsetsMake(0.0, 0.0, kbSize!.height, 0.0)
    
            srcScrollView.contentInset = contentInsets
            srcScrollView.scrollIndicatorInsets = contentInsets
    
            var aRect: CGRect = self.view.frame
            aRect.size.height -= kbSize!.height
            //you may not need to scroll, see if the active field is already visible
            if (CGRectContainsPoint(aRect, activeField!.frame.origin) == false) {
                let scrollPoint:CGPoint = CGPointMake(0.0, activeField!.frame.origin.y - kbSize!.height)
                srcScrollView.setContentOffset(scrollPoint, animated: true)
            }
        }
    
    //    func keyboardOnScreen(aNotification: NSNotification) {
    //        let info: NSDictionary  = aNotification.userInfo!
    //        let kbSize = info.valueForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue().size
    //        
    //        var bkgndRect: CGRect! = activeField?.superview?.frame
    //        
    //        bkgndRect.size.height += kbSize!.height
    //        
    //        activeField?.superview?.frame = bkgndRect
    //        
    //        srcScrollView.setContentOffset(CGPointMake(0.0, activeField!.frame.origin.y - kbSize!.height), animated: true)
    //    }
    
        func keyboardOffScreen(notification: NSNotification){
            let contentInsets:UIEdgeInsets = UIEdgeInsetsZero
    
            srcScrollView.contentInset = contentInsets
            srcScrollView.scrollIndicatorInsets = contentInsets
    
            self.srcScrollView.setContentOffset(CGPointMake(0, -self.view.frame.origin.y/2), animated: true)
        }
    
    }
    

    【讨论】:

    • 经过一天的努力,我设法在 Swift 中实现了苹果的建议 + 稍微修改了他们的代码 + 对其进行了调整,使其在所有苹果设备上都能响应,所以在投反对票之前,请告诉我为什么.上面的代码都不能在所有设备和所有布局情况下正常工作。但是我的确实适用于所有苹果设备和布局情况。
    • 我想您还需要在视图消失之前取消订阅通知中心?
    【解决方案7】:

    Swift 4.2 解决方案,考虑了 UIToolbar 和 UITabBar 的可能高度。

    private func setupKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIControl.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIControl.keyboardWillHideNotification, object: nil)
    }
    
    @objc func keyboardWillShow(_ notification: Notification) {
        let userInfo: NSDictionary = notification.userInfo! as NSDictionary
        let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.size
    
        let tabbarHeight = tabBarController?.tabBar.frame.size.height ?? 0
        let toolbarHeight = navigationController?.toolbar.frame.size.height ?? 0
        let bottomInset = keyboardSize.height - tabbarHeight - toolbarHeight
    
        scrollView.contentInset.bottom = bottomInset
        scrollView.scrollIndicatorInsets.bottom = bottomInset
    }
    
    @objc func keyboardWillHide(_ notification: Notification) {
        scrollView.contentInset = .zero
        scrollView.scrollIndicatorInsets = .zero
    }
    

    而且,如果你的目标是 Joe)

    【讨论】:

    【解决方案8】:

    我要在 Apple 代码中更新的唯一内容是 keyboardWillBeHidden: 方法,以提供平滑过渡。

    // Called when the UIKeyboardWillHideNotification is sent
    - (void)keyboardWillBeHidden:(NSNotification*)aNotification
    {
        UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    
        [UIView animateWithDuration:0.4 animations:^{
            self.scrollView.contentInset = contentInsets;
        }];
        self.scrollView.scrollIndicatorInsets = contentInsets;
    
    }
    

    【讨论】:

      【解决方案9】:

      这是一个兼容 Swift 3 的答案,它也适用于导航控制器中的视图控制器 - 因为它们会更改滚动视图 contentInset.top 属性。

      override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
      
          self.registerKeyboardNotifications()
      }
      
      override func viewWillDisappear(_ animated: Bool) {
          super.viewWillDisappear(animated)
      
          self.unregisterKeyboardNotifications()
      }
      
      func registerKeyboardNotifications() {
          NotificationCenter.default.addObserver(self, selector: #selector(LoginViewController.keyboardDidShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
          NotificationCenter.default.addObserver(self, selector: #selector(LoginViewController.keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
      }
      
      func unregisterKeyboardNotifications() {
          NotificationCenter.default.removeObserver(self)
      }
      
      
      func keyboardDidShow(notification: NSNotification) {
          let userInfo: NSDictionary = notification.userInfo! as NSDictionary
          let keyboardInfo = userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue
          let keyboardSize = keyboardInfo.cgRectValue.size
      
          // Get the existing contentInset for the scrollView and set the bottom property to be the height of the keyboard
          var contentInset = self.scrollView.contentInset
          contentInset.bottom = keyboardSize.height
      
          self.scrollView.contentInset = contentInset
          self.scrollView.scrollIndicatorInsets = contentInset
      }
      
      func keyboardWillHide(notification: NSNotification) {
          var contentInset = self.scrollView.contentInset
          contentInset.bottom = 0
      
          self.scrollView.contentInset = contentInset
          self.scrollView.scrollIndicatorInsets = UIEdgeInsets.zero
      }
      

      【讨论】:

        【解决方案10】:

        我发现上面的答案已经过时了。滚动时也不完美。

        这是一个快速版本。

        它将在文本字段的正下方滚动,没有多余的空间。它会恢复到它第一次出现时的样子。

        //add observer
        override func viewDidLoad() {
            super.viewDidLoad()
        
            NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ARVHttpPlayVC.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
            NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ARVHttpPlayVC.keyboardDidHide(_:)), name: UIKeyboardDidHideNotification, object: nil)
        }
        
        func keyboardDidShow(notification: NSNotification) {
            let userInfo: NSDictionary = notification.userInfo!
            let keyboardSize = userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)!.CGRectValue.size
            let difference = keyboardSize.height - (self.view.frame.height - inputTextField.frame.origin.y - inputTextField.frame.size.height)
            if difference > 0 {
                var contentInset:UIEdgeInsets = self.scrollView.contentInset
                contentInset.bottom = difference
                self.scrollView.contentInset = contentInset
        
                let scrollPoint = CGPointMake(0, difference)
                self.scrollView.setContentOffset(scrollPoint, animated: true)
            }
        
        }
        
        func keyboardDidHide(notification: NSNotification) {
            let contentInset:UIEdgeInsets = UIEdgeInsetsZero
            self.scrollView.contentInset = contentInset
        }
        
        //remove observer
        deinit {
            NSNotificationCenter.defaultCenter().removeObserver(self)
        }
        

        【讨论】:

        • 它确实向上滚动了一点,但不足以暴露整个高度。我正在使用 Swift 2.3 并在 iphone 5 上对其进行测试。
        【解决方案11】:

        这是我一直在使用的。这很简单,而且效果很好。

        #pragma mark - Scrolling
        
        -(void)scrollElement:(UIView *)view toPoint:(float)y
        {
            CGRect theFrame = view.frame;
            float orig_y = theFrame.origin.y;
            float diff = y - orig_y;
        
            if (diff < 0) 
                [self scrollToY:diff];
        
            else 
                [self scrollToY:0];
        }
        
        -(void)scrollToY:(float)y
        {
            [UIView animateWithDuration:0.3f animations:^{
                [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                self.view.transform = CGAffineTransformMakeTranslation(0, y);
            }];
        }
        

        使用UITextField委托调用textFieldDidBeginEditing:向上移动您的视图,并添加通知观察者以在键盘隐藏时使视图恢复正常:

        -(void)textFieldDidBeginEditing:(UITextField *)textField
        {
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
        
            if (self.view.frame.origin.y == 0)
                [self scrollToY:-90.0];  // y can be changed to your liking
        
        }
        
        -(void)keyboardWillHide:(NSNotification*)note
        {
            [self scrollToY:0];
            [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
        }
        

        【讨论】:

          【解决方案12】:

          这是 Swift

          改进的最终代码
              //MARK: UITextFieldDelegate
          func textFieldDidBeginEditing(textField: UITextField!) {    //delegate method
              self.textField = textField
          }
          
          func textFieldShouldReturn(textField: UITextField!) -> Bool {   //delegate method
              textField.resignFirstResponder()
              return true
          }
          
          //MARK: Keyboard handling
          override func viewWillDisappear(animated: Bool) {
              super.viewWillDisappear(animated)
              unregisterKeyboardNotifications()
          }
          
          func registerKeyboardNotifications() {
              NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UCProfileSettingsViewController.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
              NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(UCProfileSettingsViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
          }
          
          func unregisterKeyboardNotifications() {
              NSNotificationCenter.defaultCenter().removeObserver(self)
          }
          
          func keyboardDidShow(notification: NSNotification) {
              let userInfo: NSDictionary = notification.userInfo!
              let keyboardSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue.size
              let contentInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
              scrollView.contentInset = contentInsets
              scrollView.scrollIndicatorInsets = contentInsets
          
              var viewRect = self.view.frame
              viewRect.size.height -= keyboardSize.height
              let relativeFieldFrame: CGRect = textField.convertRect(textField.frame, toView: self.view)
              if CGRectContainsPoint(viewRect, relativeFieldFrame.origin) {
                  let scrollPoint = CGPointMake(0, relativeFieldFrame.origin.y - keyboardSize.height)
                  scrollView.setContentOffset(scrollPoint, animated: true)
              }
          
          }
          
          func keyboardWillHide(notification: NSNotification) {
              scrollView.contentInset = UIEdgeInsetsZero
              scrollView.scrollIndicatorInsets = UIEdgeInsetsZero
          }
          

          【讨论】:

          • 我认为你的逻辑是相反的 - 如果 CGRectContainsPoint 不包含 relativeFieldFrame.origin,你只想滚动。
          【解决方案13】:

          最简单的解决方案之一是使用以下协议:

          protocol ScrollViewKeyboardDelegate: class {
              var scrollView: UIScrollView? { get set }
          
              func registerKeyboardNotifications()
              func unregisterKeyboardNotifications()
          }
          
          extension ScrollViewKeyboardDelegate where Self: UIViewController {
              func registerKeyboardNotifications() {
                  NotificationCenter.default.addObserver(
                      forName: UIResponder.keyboardWillChangeFrameNotification,
                      object: nil,
                      queue: nil) { [weak self] notification in
                          self?.keyboardWillBeShown(notification)
                  }
          
                  NotificationCenter.default.addObserver(
                      forName: UIResponder.keyboardWillHideNotification,
                      object: nil,
                      queue: nil) { [weak self] notification in
                          self?.keyboardWillBeHidden(notification)
                  }
              }
          
              func unregisterKeyboardNotifications() {
                  NotificationCenter.default.removeObserver(
                      self,
                      name: UIResponder.keyboardWillChangeFrameNotification,
                      object: nil
                  )
                  NotificationCenter.default.removeObserver(
                      self,
                      name: UIResponder.keyboardWillHideNotification,
                      object: nil
                  )
              }
          
              func keyboardWillBeShown(_ notification: Notification) {
                  let info = notification.userInfo
                  let key = (info?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)
                  let aKeyboardSize = key?.cgRectValue
          
                  guard let keyboardSize = aKeyboardSize,
                      let scrollView = self.scrollView else {
                          return
                  }
          
                  let bottomInset = keyboardSize.height
                  scrollView.contentInset.bottom = bottomInset
                  scrollView.scrollIndicatorInsets.bottom = bottomInset
                  if let activeField = self.view.firstResponder {
                      let yPosition = activeField.frame.origin.y - bottomInset
                      if yPosition > 0 {
                          let scrollPoint = CGPoint(x: 0, y: yPosition)
                          scrollView.setContentOffset(scrollPoint, animated: true)
                      }
                  }
              }
          
              func keyboardWillBeHidden(_ notification: Notification) {
                  self.scrollView?.contentInset = .zero
                  self.scrollView?.scrollIndicatorInsets = .zero
              }
          }
          
          extension UIView {
              var firstResponder: UIView? {
                  guard !isFirstResponder else { return self }
                  return subviews.first(where: {$0.firstResponder != nil })
              }
          }
          

          当你想使用这个协议时,你只需要遵守它并在你的控制器中分配你的滚动视图,如下所示:

          class MyViewController: UIViewController {
                @IBOutlet var scrollViewOutlet: UIScrollView?
                var scrollView: UIScrollView?
          
                public override func viewDidLoad() {
                  super.viewDidLoad()
          
                  self.scrollView = self.scrollViewOutlet
                  self.scrollView?.isScrollEnabled = true
                  self.registerKeyboardNotifications()
              }
          
              extension MyViewController: ScrollViewKeyboardDelegate {}
          
              deinit {
                 self.unregisterKeyboardNotifications()
              }
          
          }
          

          【讨论】:

            【解决方案14】:

            我会这样做。这是很多代码,但它确保当前焦点的 textField 在“可用空间”中垂直居中:

            - (void)viewWillAppear:(BOOL)animated {
                [super viewWillAppear:animated];
                [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
                [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
            }
            
            - (void)viewWillDisappear:(BOOL)animated {
                [super viewWillDisappear:animated];
                [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
                [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
            }
            
            - (void)keyboardWillShow:(NSNotification *)notification {
                NSDictionary *info = [notification userInfo];
                NSValue *keyBoardEndFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
                CGSize keyboardSize = [keyBoardEndFrame CGRectValue].size;
                self.keyboardSize = keyboardSize;
            
                [self adjustScrollViewOffsetToCenterTextField:self.currentTextField];
            }
            
            - (void)keyboardWillHide:(NSNotification *)notification {
                self.keyboardSize = CGSizeZero;
            }
            
            - (IBAction)textFieldGotFocus:(UITextField *)sender {
                sender.inputAccessoryView = self.keyboardAccessoryView;
                self.currentTextField = sender;
                [self adjustScrollViewOffsetToCenterTextField:sender];    
            }
            
            - (void)adjustScrollViewOffsetToCenterTextField:(UITextField *)textField
            {
                CGRect textFieldFrame = textField.frame;
                float keyboardHeight = MIN(self.keyboardSize.width, self.keyboardSize.height);
            
                float visibleScrollViewHeight = self.scrollView.frame.size.height - keyboardHeight;
                float offsetInScrollViewCoords = (visibleScrollViewHeight / 2) - (textFieldFrame.size.height / 2);
            
                float scrollViewOffset = textFieldFrame.origin.y - offsetInScrollViewCoords;
            
            
                [UIView animateWithDuration:.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
                    self.scrollView.contentOffset = CGPointMake(self.scrollView.contentOffset.x, scrollViewOffset);
                }completion:NULL];
            
            }
            
            you'll need these two properties in your @interface...
            @property (nonatomic, assign) CGSize keyboardSize;
            @property (nonatomic, strong) UITextField *currentTextField;
            

            请注意,- (IBAction)textFieldGotFocus: 操作与每个 textField 的 DidBeginEditing 状态相关联。

            另外,从键盘通知中获取动画持续时间并将其用于滚动视图动画而不是固定值会更好一些,但请告我,这对我来说已经足够了 ;)

            【讨论】:

              【解决方案15】:

              如果您不想计算太多,请使用以下扩展:

              func scrollSubviewToBeVisible(subview: UIView, animated: Bool) {
                  let visibleFrame = UIEdgeInsetsInsetRect(self.bounds, self.contentInset)
                  let subviewFrame = subview.convertRect(subview.bounds, toView: self)
                  if (!CGRectContainsRect(visibleFrame, subviewFrame)) {
                      self.scrollRectToVisible(subviewFrame, animated: animated)
                  }
              }
              

              也许你想让你的 UITextField 始终可见:

              func textViewDidChange(textView: UITextView) {
                  self.scrollView?.scrollSubviewToBeVisible(textView, animated: false)
              }
              

              【讨论】:

                【解决方案16】:

                在 Swift 3 中试试这个代码:

                override func viewDidAppear(_ animated: Bool) {
                    setupViewResizerOnKeyboardShown()
                }
                
                func setupViewResizerOnKeyboardShown() {
                    NotificationCenter.default.addObserver(self,
                                                           selector: #selector(self.keyboardWillShowForResizing),
                                                           name: Notification.Name.UIKeyboardWillShow,
                                                           object: nil)
                    NotificationCenter.default.addObserver(self,
                                                           selector: #selector(self.keyboardWillHideForResizing),
                                                           name: Notification.Name.UIKeyboardWillHide,
                                                           object: nil)
                }
                
                func keyboardWillShowForResizing(notification: Notification) {
                    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
                        let window = self.view.window?.frame {
                        // We're not just minusing the kb height from the view height because
                        // the view could already have been resized for the keyboard before
                        self.view.frame = CGRect(x: self.view.frame.origin.x,
                                                 y: self.view.frame.origin.y,
                                                 width: self.view.frame.width,
                                                 height: window.origin.y + window.height - keyboardSize.height)
                
                    } else {
                        debugPrint("We're showing the keyboard and either the keyboard size or window is nil: panic widely.")
                    }
                }
                
                func keyboardWillHideForResizing(notification: Notification) {
                    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
                        let viewHeight = self.view.frame.height
                        self.view.frame = CGRect(x: self.view.frame.origin.x,
                                                 y: self.view.frame.origin.y,
                                                 width: self.view.frame.width,
                                                 height: viewHeight) //viewHeight + keyboardSize.height
                
                    } else {
                        debugPrint("We're about to hide the keyboard and the keyboard size is nil. Now is the rapture.")
                    }
                }
                
                deinit {
                        NotificationCenter.default.removeObserver(self)
                    }
                

                【讨论】:

                  【解决方案17】:

                  Swift 5 解决方案基于上述Masa solution - 与之相关的更改:

                  • 使用keyboardFrameEndUserInfoKey 代替 keyboardFrameBeginUserInfoKey,因为 keyboardFrameBeginUserInfoKey 可以在第一次显示返回其他值 如此处所述:keyboard height varies when appearing
                  • 使用“will”而不是“did”通知并将其更改为 Swift 5 键名称:UIResponder.keyboardWillShowNotification/UIResponder.keyboardWillHideNotification 而不是 NSNotification.Name.UIKeyboardDidShow/NSNotification.Name.UIKeyboardDidHide

                  代码:

                  override func viewDidLoad() {
                      super.viewDidLoad()
                      registerForKeyboardNotifications()
                  }
                  
                  func registerForKeyboardNotifications() {
                      NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardAppear(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
                      NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDisappear(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
                  }
                  
                  @objc func onKeyboardAppear(_ notification: NSNotification) {
                      guard let info = notification.userInfo, let kbSize = (info[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size else { return }
                  
                      let insets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0)
                  
                      scrollView.contentInset = insets
                      scrollView.scrollIndicatorInsets = insets
                  
                      //Other changes if needed
                  }
                  
                  deinit {
                      NotificationCenter.default.removeObserver(self)
                  }
                  

                  【讨论】:

                  • 您的答案中缺少函数onKeyboardDisappear :)
                  【解决方案18】:

                  您实际上不需要 UIScrollView 来执行此操作。我使用了这段代码,它对我有用:

                  -(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
                  {
                  
                     if (textField==_myTextField)
                     {
                        [self keyBoardAppeared];
                     }
                     return true;
                  }
                  
                  -(void)textFieldDidEndEditing:(UITextField *)textField {
                     if (textField==_myTextField)
                     {
                        [self keyBoardDisappeared];
                     }
                  }
                  
                  -(void) keyBoardAppeared
                  {
                     CGRect frame = self.view.frame;
                  
                  [UIView animateWithDuration:0.3
                                        delay:0
                                      options: UIViewAnimationCurveEaseOut
                                   animations:^{
                                       self.view.frame = CGRectMake(frame.origin.x, frame.origin.y-215, frame.size.width, frame.size.height);
                                   }
                                   completion:^(BOOL finished){
                  
                                   }];
                  }
                  
                  -(void) keyBoardDisappeared
                  {
                     CGRect frame = self.view.frame;
                  
                    [UIView animateWithDuration:0.3
                                        delay:0
                                      options: UIViewAnimationCurveEaseOut
                                   animations:^{
                                       self.view.frame = CGRectMake(frame.origin.x, frame.origin.y+215, frame.size.width, frame.size.height);
                                   }
                                   completion:^(BOOL finished){
                  
                                   }];
                  }
                  

                  【讨论】:

                  • 问题:使用硬编码值。上下移动整个 UI,这通常会弄乱视图的外观。
                  【解决方案19】:

                  您可以使用UIScrollView中的属性contentOffset进行滚动,例如,

                  CGPoint offset = scrollview.contentOffset;
                  offset.y -= KEYBOARD_HEIGHT + 5;
                  scrollview.contentOffset = offset;
                  

                  还有一种方法可以进行动画滚动。

                  至于您的第二次编辑没有正确滚动的原因,可能是因为您似乎认为每次编辑开始时都会出现一个新键盘。您可以尝试检查是否已经针对“键盘”可见位置进行了调整(同样在还原之前检查键盘可见性)。

                  更好的解决方案可能是监听键盘通知,例如:

                  [[NSNotificationCenter defaultCenter] addObserver:self
                                                           selector:@selector(keyboardDidShow:)
                                                               name:UIKeyboardDidShowNotification
                                                             object:nil];
                  [[NSNotificationCenter defaultCenter] addObserver:self
                                                           selector:@selector(keyboardWillHide:)
                                                               name:UIKeyboardWillHideNotification
                                                             object:nil];
                  

                  【讨论】:

                    【解决方案20】:

                    我现在知道这是一个老问题,但我认为它可能对其他人有所帮助。我想为我拥有的一些应用程序实现一些更容易的东西,所以我为此创建了一个类。如果需要,可以在这里下载:https://github.com/sdernley/iOSTextFieldHandler

                    就像将所有 UITextField 设置为具有 self 的委托一样简单

                    textfieldname.delegate = self;
                    

                    然后将其添加到您的视图控制器中,并使用您的滚动视图和提交按钮的名称

                    - (void)textFieldDidBeginEditing:(UITextField *)textField
                    {
                        [iOSTextFieldHandler TextboxKeyboardMover:containingScrollView tf:textField btn:btnSubmit];
                    }
                    

                    【讨论】:

                      【解决方案21】:

                      以下是我的有效解决方案(5 个步骤)

                      Step1:添加一个观察者来捕捉哪个 UITEXTFIELD 或 UITEXTVIEW ShoudBeginEditing(其中对象被初始化或 ViewDidLoad。

                      [[NSNotificationCenter defaultCenter] addObserver:self 
                                                               selector:@selector(updateActiveField:)
                                                                   name:@"UPDATE_ACTIVE_FIELD" object:nil];
                      

                      Step2:当..ShouldBeginEditing 使用UITEXTFIELD 或UITEXTVIEW 的OBJECT 时发布通知

                      -(BOOL)textViewShouldBeginEditing:(UITextView *)textView {
                      
                      [[NSNotificationCenter defaultCenter] postNotificationName:@"UPDATE_ACTIVE_FIELD" 
                                                                          object:textView];
                      return YES;
                      }
                      

                      Step3:(Step1调用)分配当前UITEXTFIELD或UITEXTVIEW的方法

                      -(void) updateActiveField: (id) sender {
                          activeField = [sender object];
                      }
                      

                      Step4:添加键盘观察器UIKeyboardWillShowNotification(与Step1相同)

                      [[NSNotificationCenter defaultCenter] addObserver:self
                                                               selector:@selector(keyboardWasShown:)
                                                                   name:UIKeyboardDidShowNotification object:nil];
                      

                      和方法:

                      // Called when the UIKeyboardDidShowNotification is sent.
                      - (void)keyboardWasShown:(NSNotification*)aNotification
                      {
                          NSDictionary* info = [aNotification userInfo];
                          CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
                          UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
                      
                          _currentEdgeInsets = self.layoutPanel.contentInset; // store current insets to restore them later
                          self.layoutPanel.contentInset = contentInsets;
                          self.layoutPanel.scrollIndicatorInsets = contentInsets;
                      
                          // If active text field is hidden by keyboard, scroll it so it's visible
                          CGRect aRect =  self.view.frame;
                          aRect.size.height -= kbSize.height;
                      
                          UIWindow *window = [[UIApplication sharedApplication] keyWindow];
                          CGPoint p = [activeField convertPoint:activeField.bounds.origin toView:window];
                      
                          if (!CGRectContainsPoint(aRect, p) ) {
                              CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y +kbSize.height);
                             [self.layoutPanel setContentOffset:scrollPoint animated:YES];
                             self.layoutPanel.scrollEnabled = NO;
                          }
                      }
                      

                      Step5:添加键盘观察器UIKeyboardWillHideNotification(与步骤1相同)

                          [[NSNotificationCenter defaultCenter] addObserver:self
                                                                   selector:@selector(keyboardWillBeHidden:)
                                                                       name:UIKeyboardWillHideNotification object:nil];
                      

                      和方法:

                      // Called when the UIKeyboardWillHideNotification is sent
                      - (void)keyboardWillBeHidden:(NSNotification*)aNotification
                      {
                          self.layoutPanel.contentInset = _currentEdgeInsets;
                          self.layoutPanel.scrollIndicatorInsets = _currentEdgeInsets;
                          self.layoutPanel.scrollEnabled = YES;
                      }
                      

                      记得移除观察者!

                      【讨论】:

                        【解决方案22】:

                        我使用了 Sudheer Palchuri 提供的这个答案 https://stackoverflow.com/users/2873919/sudheer-palchuri https://stackoverflow.com/a/32583809/6193496

                        在 ViewDidLoad 中,注册通知:

                        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DetailsViewController.keyboardWillShow(_:)), name:UIKeyboardWillShowNotification, object: nil)
                        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DetailsViewController.keyboardWillHide(_:)), name:UIKeyboardWillHideNotification, object: nil)
                        

                        添加以下观察者方法,当键盘出现时自动滚动。

                        func textFieldShouldReturn(textField: UITextField) -> Bool {
                        textField.resignFirstResponder()
                        return true
                        }
                        
                        func keyboardWillShow(notification:NSNotification){
                        
                        var userInfo = notification.userInfo!
                        var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
                        keyboardFrame = self.view.convertRect(keyboardFrame, fromView: nil)
                        
                        var contentInset:UIEdgeInsets = self.scrollView.contentInset
                        contentInset.bottom = keyboardFrame.size.height
                        self.scrollView.contentInset = contentInset
                        }
                        
                        func keyboardWillHide(notification:NSNotification){
                        
                        var contentInset:UIEdgeInsets = UIEdgeInsetsZero
                        self.scrollView.contentInset = contentInset
                        }
                        

                        【讨论】:

                          【解决方案23】:

                          我的解决方案有 4 个步骤:
                          - 第1步:当键盘出现时函数监听

                          - (void)keyboardWasShown:(NSNotification *)notification {
                          // Get the size of the keyboard.
                          CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
                          //top: 64 for navigation bar, 0 for without navigation
                          UIEdgeInsets contentInsets = UIEdgeInsetsMake(64, 0, keyboardSize.height, 0);
                          _scrollView.contentInset = contentInsets;
                          _scrollView.scrollIndicatorInsets = contentInsets;
                          }
                          

                          - 第 2 步:函数在键盘消失时进行侦听

                          - (void)keyboardWillHide:(NSNotification *)notification {
                          //top: 64 for navigatiob bar
                          UIEdgeInsets contentInsets = UIEdgeInsetsMake(64, 0, 0, 0);
                          [_editScrollView setContentInset: contentInsets];
                          [_editScrollView setScrollIndicatorInsets: contentInsets];
                          }
                          

                          - 第三步:将这些功能添加到通知中心:

                          - (void)viewWillAppear:(BOOL)animated{
                          [super viewWillAppear:animated];
                          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
                          [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
                          }
                          

                          - 第 4 步:当视图控制器消失时移除监听

                          - (void)viewDidDisappear:(BOOL)animated{
                          [super viewDidDisappear:animated];
                          [[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardDidShowNotification object:nil];
                          [[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillHideNotification object:nil];
                          }
                          

                          【讨论】:

                            猜你喜欢
                            • 2015-02-15
                            • 1970-01-01
                            • 2015-08-01
                            • 2017-08-09
                            • 1970-01-01
                            • 1970-01-01
                            • 2014-04-10
                            • 2015-02-02
                            • 2013-02-25
                            相关资源
                            最近更新 更多