键盘出现时如何滚动 UIScrollView?

Posted

技术标签:

【中文标题】键盘出现时如何滚动 UIScrollView?【英文标题】:How do I scroll the UIScrollView when the keyboard appears? 【发布时间】: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];

有什么想法吗?

【问题讨论】:

【参考方案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 1、link 2、link 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)

【讨论】:

iPhone X 是否考虑到标签栏下的空间?这是 iOS 条纹出现的地方。 iOS9+ 不需要移除观察者developer.apple.com/documentation/foundation/notificationcenter/… 是的,你是对的。我已经相应地更新了答案。【参考方案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://***.com/users/2873919/sudheer-palchuri https://***.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];

【讨论】:

以上是关于键盘出现时如何滚动 UIScrollView?的主要内容,如果未能解决你的问题,请参考以下文章

键盘出现时的UIScrollView

当键盘出现滚动视图时文本字段消失

键盘消失时,UIScrollView 不会向下滚动到其原始位置

显示键盘时如何决定滚动哪个 UIScrollView

iPhone - 出现键盘时如何滚动 UITextField 并调整 UITextView 的大小

当我在显示的键盘上单击文本字段两次时,iOS UIScrollView 无法滚动