0

Although this problem has been described on many occasions, I'm asking this in reference and in the context of IOS7 & Apple's proposed solution which is described in the docs here:

https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

Problem: Keyboard covers a text view. Solution: Using Apples suggested method, attach observers to keyboard events, scroll a UIScrollView uo by the keyboard height.

I've created a simple implementation of a single texfield which is a subview of a scrollview in a view controller, ensured the view controller is delegates of both and that that the correct methods are getting called.

TestViewController.h

#import <UIKit/UIKit.h>

@interface TestViewController : UIViewController <UITextFieldDelegate, UIScrollViewDelegate>

@end

TestViewController.m

#import "TestViewController.h"

@interface TestViewController ()
@property (weak, nonatomic) IBOutlet UITextField *testTextField;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;


@end

@implementation TestViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [self registerForKeyboardNotifications];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)registerForKeyboardNotifications
{
    NSLog(@"registerForKeyboardNotifications got called");


    [[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
{
    NSLog(@"keyboardWasShown got called");

    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;

    // If active text field is hidden by keyboard, scroll it so it's visible
    // Your app might not need or want this behavior.
    CGRect aRect = self.view.frame;
    aRect.size.height -= kbSize.height;
    if (!CGRectContainsPoint(aRect, self.testTextField.frame.origin) ) {
        [self.scrollView scrollRectToVisible:self.testTextField.frame animated:YES];
    }
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{

    NSLog(@"keyboardWillBeHidden got called");

    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
}

- (BOOL) textFieldShouldReturn:(UITextField *)textField
{

    [textField resignFirstResponder];
    return TRUE;
}



@end

Before Keyboard appears

After Keyboard appears

RolandFlyBoy
  • 193
  • 3
  • 14
  • 1
    EDIT: It turns out the Apple docs are at fault. Fixed and answered here http://stackoverflow.com/a/4837510/656959 – RolandFlyBoy Jan 13 '14 at 01:39

1 Answers1

0

I have edited the Apple Solution using Swift.

import UIKit

class ExampleViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var scrollView: UIScrollView!

    @IBOutlet var textField1: UITextField!
    @IBOutlet var textField2: UITextField!
    @IBOutlet var textField3: UITextField!
    @IBOutlet var textField4: UITextField!
    @IBOutlet var textField5: UITextField!

    var activeTextField: UITextField!

    // MARK: - View
    override func viewDidLoad() {
        super.viewDidLoad()
        self.textField1.delegate = self
        self.textField2.delegate = self
        self.textField3.delegate = self
        self.textField4.delegate = self
        self.textField5.delegate = self
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.registerForKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        self.unregisterFromKeyboardNotifications()
    }

    // MARK: - Keyboard

    // Call this method somewhere in your view controller setup code.
    func registerForKeyboardNotifications() {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
        center.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterFromKeyboardNotifications () {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
        center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }

    // Called when the UIKeyboardDidShowNotification is sent.
    func keyboardWasShown (notification: NSNotification) {
        let info : NSDictionary = notification.userInfo!
        let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue as CGRect!).size

        let contentInsets: UIEdgeInsets = 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 app might not need or want this behavior.
        var aRect = self.view.frame
        aRect.size.height -= kbSize.height;
        if (!CGRectContainsPoint(aRect, self.activeTextField.frame.origin) ) {
            self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true)
        }
    }

    // Called when the UIKeyboardWillHideNotification is sent
    func keyboardWillBeHidden (notification: NSNotification) {
        let contentInsets = UIEdgeInsetsZero;
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }

    // MARK: -  Text Field

    func textFieldDidBeginEditing(textField: UITextField) {
        self.activeTextField = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        self.activeTextField = nil
    }

}
whyceewhite
  • 6,317
  • 7
  • 43
  • 51
Homam
  • 5,018
  • 4
  • 36
  • 39