avoid view when opening keyboard from a UITextView inside a UITableView with custom cell

前端 未结 5 876
感动是毒
感动是毒 2021-01-07 09:04

I have a UIViewController that contains a UITableView with custom cells, inside the cell are UILabels, a couple of uneditable UI

相关标签:
5条回答
  • 2021-01-07 09:38
    I fixed the issue. Please see my solution below:
    
    1. First declare a global varibale called "activeFileld"
    @property(nonatomic,strong)id activeFiled;
    
    2. Create a method called "registerForKeyboardNotifications"
    - (void)registerForKeyboardNotifications 
    {
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(keyboardWillShow:)
                                                         name:UIKeyboardWillShowNotification object:nil]; //Posted immediately prior to the display of the keyboard
    
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(keyboardWillHide:)
                                                         name:UIKeyboardWillHideNotification object:nil]; //Posted immediately prior to the dismissal of the keyboard.
    }
    
    3. Called the above method in viewWillAppear:
    
    -(void)viewWillAppear:(BOOL)animated{
    
      [super viewWillAppear:animated];
      //Register kryboard Notification
       [self registerForKeyboardNotifications];
    }
    4. Call the Delegate method for UitextFieldd Or UitextView
    
    - (void)textFieldDidBeginEditing:(UITextField *)sender {
    
            self.activeField = sender;
    }
    - (void)textFieldDidEndEditing:(UITextField *)sender{
            self.activeField = nil;
    }
    
    - (void)textViewDidBeginEditing:(UITextView *)textView
    {
        // save the text view that is being edited
        _notes = textView.text;
    
    }
    - (void)textViewDidEndEditing:(UITextView *)textView
    {
        // release the selected text view as we don't need it anymore
        _activeField = nil;
    }
    
    5.
    
    - (void)keyboardWillShow:(NSNotification *)notification
    {
    
        if([_activeField isKindOfClass:[UITextField class]]) {
    
            NSDictionary* info = [notification userInfo];
            NSLog(@"Dictionary %@",info);
            CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
            kbRect = [self.view convertRect:kbRect fromView:nil];
    
            UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbRect.size.height, 0.0);
            self.tableView.contentInset = contentInsets;
            self.tableView.scrollIndicatorInsets = contentInsets;
    
            CGRect aRect = self.view.frame;
            aRect.size.height -= kbRect.size.height;
    
            UITextField *textField = (UITextField*)_activeField;
            if (!CGRectContainsPoint(aRect, textField.frame.origin) ) {
                [self.tableView scrollRectToVisible:textField.frame animated:YES];
            }
        }else if([_activeField isKindOfClass:[UITextView class]]) {
    
            NSDictionary* info = [notification userInfo];
            NSLog(@"Dictionary %@",info);
            CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
            kbRect = [self.view convertRect:kbRect fromView:nil];
    
            UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbRect.size.height, 0.0);
            self.tableView.contentInset = contentInsets;
            self.tableView.scrollIndicatorInsets = contentInsets;
    
            CGRect aRect = self.view.frame;
            aRect.size.height += kbRect.size.height;
    
            UITextView *activeTextView = (UITextView*)_activeField;
            if (!CGRectContainsPoint(aRect, textField.superview.superview.frame.origin) ) {
                [self.tableView scrollRectToVisible:activeTextView.superview.superview.frame animated:YES];
    
           }
    
    
       }
    
    
    
    
    
    }
    
    // Called when the UIKeyboardWillHideNotification is received
    - (void)keyboardWillHide:(NSNotification *)aNotification
    {
        UIEdgeInsets contentInsets = UIEdgeInsetsZero;
        self.tableView.contentInset = contentInsets;
        self.tableView.scrollIndicatorInsets = contentInsets;
    }
    
    0 讨论(0)
  • 2021-01-07 09:42

    Two solutions:

    Preferred: use a UITableViewController instead of a UIViewController as that one will automatically make sure that your keypad won't hide the editable field.

    Hacky: How to make a UITextField move up when keyboard is present?

    0 讨论(0)
  • 2021-01-07 09:42

    I've always used a two fold solution for this.

    1. Resize table so it now fits in the smaller area.
    2. Scroll to the cell we want visible. (we needed to re-size the table for this or you'd still wind up being unable to get to the last couple of cells in the table.)

    To do this, I register keyboard show/hide events and act accordingly when they get called.

    - (void)keyboardWillShow:(NSNotification *)note {
        [self updateForKeyboardShowHide:note appearing:YES];
    }
    - (void)keyboardWillHide:(NSNotification *)note {
        [self updateForKeyboardShowHide:note appearing:NO];
    }
    
    - (void)updateForKeyboardShowHide:(NSNotification *)note appearing:(BOOL)isAppearing {
        // ignore notifications if our view isn't attached to the window
        if (self.view.window == nil)
            return;
    
        CGFloat directionalModifier = isAppearing?-1:1;
        CGRect keyboardBounds = [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
        CGFloat animationDuration = [[note.userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
    
        // figure out table re-size based on keyboard
        CGFloat keyboardHeight;
        UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
        if (UIInterfaceOrientationIsPortrait(orientation))
            keyboardHeight = keyboardBounds.size.height;
        else 
            keyboardHeight = keyboardBounds.size.width;
    
        [UIView animateWithDuration:animationDuration animations:^{
            // resize table
            CGRect newFrame = table.frame;
            newFrame.size.height += [self calculateKeyboardOffsetWithHeight:keyboardHeight] * directionalModifier;
            table.frame = newFrame;        
        }  completion:^(BOOL finished){
            // scroll to selected cell
            if (isAppearing) {
                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:textFieldInEdit.tag inSection:0];
                [table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
            }
        }];
    }
    
    - (CGFloat)calulateKeyboardOffsetWithHeight:(CGFloat)keyboardHeight {
        // This depends on the size and position of your table.
        //   If your table happen to go all the way to the bottom of
        // the screen, you'll needs to adjust it's size by the whole keyboard height.
        // You might as well ditch this method and inline the value.
        return keyboardHeight;
    
        //   My table did not go to the bottom of the screen and the position was
        // change dynamically so and there was long boring calculation I needed to
        // do to figure out how much my table needed to shrink/grow.
    }
    
    0 讨论(0)
  • 2021-01-07 09:57

    When your table view contains data entry fields like a UITextField or a UITextView and the table view is long enough to cover the screen, you will have a problem accessing data entry fields that are hidden by the keyboard.
    To overcome this problem two solutions are:

    1. The easiest and recommended way is to use a UITableViewController instead of UIViewController, which automatic make sure keypad won't hide the editable field (If possible use this approach to avoid U.I. adjustment inconvenience)

    2. If you use a UIViewController and a UITableView as its subview. You can scroll your UI’s frame by observing the UIKeyboardWillShowNotification and UIKeyboardWillHideNotification

      - (void)registerForKeyboardNotifications 
      {
              [[NSNotificationCenter defaultCenter] addObserver:self
                                                       selector:@selector(keyboardWillShow:)
                                                           name:UIKeyboardWillShowNotification object:nil]; //Posted immediately prior to the display of the keyboard
      
              [[NSNotificationCenter defaultCenter] addObserver:self
                                                       selector:@selector(keyboardWillHide:)
                                                           name:UIKeyboardWillHideNotification object:nil]; //Posted immediately prior to the dismissal of the keyboard.
      }
      
      
      - (void)keyboardWillShow:(NSNotification *)aNotification 
      {  
          CGRect keyboardBounds = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
      
          [UIView beginAnimations:nil context:nil];
          [UIView setAnimationBeginsFromCurrentState:YES];
      
          self.tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardBounds.size.height, 0); //when keyboard is up, that time just bring your text filed above the keyboard
          self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, keyboardBounds.size.height, 0);
      
          [self.tableView scrollToRowAtIndexPath:[self findIndexPathToScroll]
                                atScrollPosition:UITableViewScrollPositionTop
                                        animated:YES]; //findIndexPathToScroll implementation not shown
          [UIView commitAnimations];
      }
      
      - (void)keyboardWillHide:(NSNotification *)aNotification 
      {
          [UIView beginAnimations:nil context:nil];
          [UIView setAnimationBeginsFromCurrentState:YES];
          self.tableView.contentInset = UIEdgeInsetsZero; //Once keyboard is hidden then bring back your table into your original position.
          self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero;
          [UIView commitAnimations];
      }
      
      • registerForKeyboardNotifications - call this method when you load the UITableView, ie: viewDidLoad

      • findIndexPathToScroll - (Implementation not shown) Its your business logic to prepare IndexPath where table view should scroll

      • removeObserver 'UIKeyboardWillShowNotification' and 'UIKeyboardWillHideNotification' both in dealloc and viewDidUnload
    0 讨论(0)
  • 2021-01-07 09:58

    A simple solution. Implement the heightForFooter method, and let it return a value of (say) 100, and when you select the a cell in UITableView, they will simply slide up by that height, and the keyboard will not cover the view.

    0 讨论(0)
提交回复
热议问题