Dan
Dan

Reputation: 2344

UITableView doesn't scroll when keyboard appears

I have attempted Apple's example here:

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

However, it doesn't seem to work so I'm clearly missing something along the way, just can't figure out what.

I have a ViewController.h containing:

@interface PreferencesViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, defaultLocationChoice, UITextFieldDelegate, UIScrollViewDelegate>

@property (nonatomic, retain) NSString *defaultLocation;
@property (nonatomic, retain) NSString *defaultTestType;
@property (nonatomic, assign) id <defaultLocationChoice> locationDelegate;
@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, strong) IBOutlet UITextField *locationnameTextField;
@property (nonatomic, strong) IBOutlet UITextField *locationaddressTextField;
@property (strong, nonatomic) IBOutlet UITableView *scrollView;
@property (nonatomic, strong) IBOutlet UITextField *activeField;

There are all Synthesized in the .m file.

I have the Apple code has follows in ViewController.m

- (void)viewDidLoad
{
    NSUserDefaults *sharedPref = [NSUserDefaults standardUserDefaults];
    defaultLocation =[sharedPref stringForKey:@"defaultLocation"];
    defaultTestType =[sharedPref stringForKey:@"defaultTestType"];

    [self registerForKeyboardNotifications];


    self.navigationItem.title = @"Preferences";

    [super viewDidLoad];

}

- (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;
}

- (void)textFieldDidBeginEditing:(UITextField *)textField

{
    activeField = textField;
}



- (void)textFieldDidEndEditing:(UITextField *)textField

{
    activeField = nil;
}

The Cells containing the TextFields are dealt with in CellForRowAtIndexPath as below (full code not shown):

  case 2:
            switch (indexPath.row) {
                case 0:

                    prefCell.textLabel.text = @"";
                    prefCell.accessoryType = UITableViewCellAccessoryNone;
                    prefCell.highlighted = NO;
                    locationnameTextField.frame = CGRectMake(5, 12, 300, 30);
                    locationnameTextField.font = [UIFont systemFontOfSize:13.0f];
                    locationnameTextField.placeholder = @"Enter location name i.e. New York, NY";
                    locationnameTextField.delegate = self;
                    locationnameTextField.returnKeyType = UIReturnKeyDone;
                    [prefCell.contentView addSubview:locationnameTextField];

                    break;
                case 1:
                    prefCell.textLabel.text = @"";
                    prefCell.accessoryType = UITableViewCellAccessoryNone;

                    locationaddressTextField.frame = CGRectMake(5, 12, 300, 30);
                     locationaddressTextField.font = [UIFont systemFontOfSize:13.0f];
                    locationaddressTextField.placeholder = @"Enter location address i.e. mcs.newyork.com";
                    locationaddressTextField.clearsOnBeginEditing = YES;
                    locationaddressTextField.delegate = self;
                    locationaddressTextField.returnKeyType = UIReturnKeyDone;

                    [prefCell.contentView addSubview:locationaddressTextField];

                    break;
            }

On running the app the keyboard pops up and nothing happens.

Apples example is for a View so the only code I changed above was self.view.frame to self.tableView.frame to no effect.

I added the ScrollView as an addition as I didn't have one. My other ViewControllers with embedded TableView don't require a ScrollView to scroll.

The hierarchy is as follows:

enter image description here

Any help would be great, thanks

Upvotes: 0

Views: 1262

Answers (3)

Cristina Sita
Cristina Sita

Reputation: 376

Since I found it, I use TPKeyboardAvoiding

It is working great, and is very easy to setup:

  1. Add a UIScrollView into your view controller's xib
  2. Set the scroll view's class to TPKeyboardAvoidingScrollView (still in the xib, via the identity inspector)
  3. Place all your controls within that scrollview

Upvotes: 0

vikmalhotra
vikmalhotra

Reputation: 10071

I was scratching my head with the same problem when I noticed the superview of textfield. If I'm right, you have the textfield inside a cell of tableview.

Now, in your keyboardWasShown: method, you are checking whether active text field is hidden under the keyboard like this:

if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
    CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
    [scrollView setContentOffset:scrollPoint animated:YES];
} 

The if condition will never be true in your case. Since the superview of active text field is a cell, the activeField.frame.origin will return a point in reference to a UITableViewCell, not in reference to your UIView.

Hence, what you need to do is check if the cell containing the active text field is hidden under the keyboard, something like this:

CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, cellForActiveField.frame.origin) ) {
    CGPoint scrollPoint = CGPointMake(0.0, cellForActiveField.frame.origin.y-kbSize.height);
    [scrollView setContentOffset:scrollPoint animated:YES];
} 

To find the cell containing active text field, you need to set the tag property of textfield in tableView:cellForIndexPath: method and then check for the tag in textFieldDidBeginEditing: method.

For more details, refer this question as well.

Hope this helps.

Upvotes: 0

Saurabh Singh
Saurabh Singh

Reputation: 247

You have to do as following:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
 [yourTextField resignFirstResponder];
}

Upvotes: 1

Related Questions