8

I have a UITableViewController with many cells, each cell contains four text fields vertical on each other, a pop over is presented by tapping on any text field, however, this pop over contains a text field when tapped the keyboard is fired and most likely the pop over will be shifted up to prevent the keyboard from hiding its text field (this is the default behavior of the pop over), but in the background (the dimmed view), the tableViewController loses its correct scrolling behavior to keep the pop over presenting-textField on the track while the keyboard is visible ..

a sample project can be downloaded here.

how can I offset the table view to keep the pop over presenting-textField on screen while keyboard is visible in this case ?

I tried the well-known TPKeyboardAvoiding library but it didn't solve the issue.

p.s. tableViewController works well for the first 3 or 4 keyboard firings, but loses precise scrolling on later attempts.

Screenshot (the green text field is the text field which presented the pop over, but tableViewController scrolls to the incorrect text field indicated in red): enter image description here

any help would be highly appreciated.

EDIT: this question is not a duplicate for: Making a UITableView scroll when text field is selected because the text field that I need the table view to scroll to is the one that fires a pop over not a keyboard, and scrollToRowAtIndexPath does not work precisely in this case because each cell contains 4 text fields.

Community
  • 1
  • 1
JAHelia
  • 6,934
  • 17
  • 74
  • 134

5 Answers5

2

use (CGRect)convertRect:(CGRect)rect toView:(UIView *)view to get cell position on tableviews superview and accordingly handle the tableview offset

vje1998
  • 691
  • 6
  • 19
1

Here is my solution : Change into TableViewController.m

1. Register for keyboard Notifications (UIKeyboardWillShowNotification, UIKeyboardWillHideNotification)

2. Create local variables:

CGSize _currentPopoverContentSize; //if you want to have custom size for popover

UIView *_currentPopoverSender; //to remember from wich view you will present popover

BOOL _keyboardIsShown; //enable in keyboardWillShow, and disable in keyboardWillHide

3. In my presentPopover method:

- (void)presentPopoverControllerWithSize:(CGSize)size fromView:(UIView *)sender{

MyController *controller = [[[MyController alloc] init] autorelease];

if (self.popover)
{
    [_popover release];
    _popover = nil;
}

_popover = [[UIPopoverController alloc] initWithContentViewController:controller];
_popover.popoverContentSize = size;
_popover.delegate = self;

//checking if keyboard is shown - if NO, than present popover, if YES - just `resignFirstResponder` for your _`activeTextField`(you can set it in -textFieldDidBeginEditing: and nullify in -textFieldDidEndEditing:)
if (!_keyboardIsShown)
{
    [_popover presentPopoverFromRect:[sender bounds]
                              inView:sender
            permittedArrowDirections:UIPopoverArrowDirectionUp
                            animated:YES];
    _popOver.popoverContentSize = CGSizeMake(320, 700);

}
else
{
    [_activeTextField resignFirstResponder];
}

_currentPopoverContentSize = size;
_currentPopoverSender = sender;
}

4. Than:

- (void)keyboardWillBeHidden:(NSNotification*)aNotification{

[UIView animateWithDuration:0.3
                 animations:^{
                     //do some stuff
                  _popOver.popoverContentSize = CGSizeMake(320, 700);

                 } completion:^(BOOL finished) {

                     if (_popover && _currentPopoverSender)
                     {
                         [_popover presentPopoverFromRect:[_currentPopoverSender bounds]
                                                   inView:_currentPopoverSender
                                 permittedArrowDirections:UIPopoverArrowDirectionUp
                                                 animated:YES];
                     }

                 }];

_keyboardIsShown = NO;
}

5.:

-(void)textFieldDidBeginEditing:(UITextField *)textField{

    [textField resignFirstResponder];
    [self presentPopoverControllerWithSize:textField.frame.size fromView:_activeText];

//     self.vc = [[self storyboard] instantiateViewControllerWithIdentifier:@"ProductSourcePopOver"];
//
//    if(_popOver == nil){   //make sure popover isn't displayed more than once in the view
//        _popOver = [[UIPopoverController alloc]initWithContentViewController:self.vc];
//    }
//    _popOver.popoverContentSize = CGSizeMake(320, 700);
//
//    [_popOver presentPopoverFromRect:_activeText.frame inView:_activeText permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
//    _popOver.delegate = self;

}

This might helps you :)

Yuyutsu
  • 2,509
  • 22
  • 38
0

Change the entire view frame size.

For example, keyboard height is 100 then,

CGRect frame = self.view.frame;
self.view.frame = CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height - keyboardHeight);

Then call didSelectRowAtIndexPath method again for the same indexPath, so it will reload the popover.

This is just a base idea, there might be some modifications required to achieve exact behavior.

Hope this will help you.

Mrunal
  • 13,982
  • 6
  • 52
  • 96
0

How about add the tag(00 01 02 03, 10 11 12 13...etc) for each UITextfield in the cell, From tens digit you can know which cell, from single digits you know which textfield.

Kobe Yu
  • 121
  • 1
  • 5
  • i tried something like this but the problem not how to reach out to the textfield but how to offset the table view to match the text field – JAHelia Jan 04 '15 at 05:47
0

Register for UIKeyboardWillShowNotification and when that selector gets triggered, call your pop over code:

[self presentPopoverControllerWithSize:textField.frame.size fromView:_activeText];

The reason for this is that the iOS handles itself presenting the popover and handling it's frame. So it's generally a good practice to present the pop over after the keyboard is shown.

Hope this helps..

Henit Nathwani
  • 442
  • 3
  • 10