【问题标题】:avoid view when opening keyboard from a UITextView inside a UITableView with custom cell从带有自定义单元格的 UITableView 内的 UITextView 打开键盘时避免查看
【发布时间】:2015-08-17 14:49:14
【问题描述】:

我有一个UIViewController,其中包含一个带有自定义单元格的UITableView,该单元格内部是UILabels、几个不可编辑的UITextView 和一个可编辑的UITextView。现在,当我点击靠近桌子底部或底部的UITextView 之一时,UITextView 被键盘覆盖。我试过http://cocoawithlove.com/2008/10/sliding-uitextfields-around-to-avoid.html,它适用于文本字段/文本视图,但不适用于带有自定义单元格的表格。任何帮助或建议如何解决这个问题?

【问题讨论】:

    标签: iphone objective-c ios uitableview uitextview


    【解决方案1】:

    当您的表格视图包含像UITextFieldUITextView 这样的数据输入字段并且表格视图的长度足以覆盖屏幕时,您将无法访问被键盘隐藏的数据输入字段。
    为了克服这个问题,有两种解决方案:

    1. 最简单且推荐的方法是使用UITableViewController 而不是UIViewController,这会自动确保键盘不会隐藏可编辑字段(如果可能,请使用此方法以避免 UI 调整不便)

    2. 如果您使用UIViewControllerUITableView 作为其子视图。你可以通过观察UIKeyboardWillShowNotificationUIKeyboardWillHideNotification来滚动你的UI框架

      - (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 - 在加载 UITableView 时调用此方法,即:viewDidLoad

      • findIndexPathToScroll - (未显示实现)它是您的业务逻辑来准备 IndexPath 应该滚动表视图的位置

      • removeObserver 'UIKeyboardWillShowNotification' 和 'UIKeyboardWillHideNotification' 都在 deallocviewDidUnload

    【讨论】:

      【解决方案2】:
      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;
      }
      

      【讨论】:

        【解决方案3】:

        两种解决方案:

        首选:使用 UITableViewController 而不是 UIViewController,因为它会自动确保您的键盘不会隐藏可编辑字段。

        HackyHow to make a UITextField move up when keyboard is present?

        【讨论】:

        • 好吧,我不能使用 UITableViewController,因为我在这个视图中有很多东西,而不仅仅是 UITableView。我会试试另一个。我稍后会回到这里。
        【解决方案4】:

        一个简单的解决方案。实现heightForFooter 方法,让它返回一个值(比如说)100,当你选择UITableView 中的a 单元格时,它们会简单地向上滑动该高度,并且键盘不会覆盖视图。

        【讨论】:

          【解决方案5】:

          我一直为此使用双重解决方案。

          1. 调整表格大小,使其适合较小的区域。
          2. 滚动到我们想要显示的单元格。 (我们需要为此重新调整表格大小,否则您仍然无法访问表格中的最后几个单元格。)

          为此,我注册了键盘显示/隐藏事件,并在它们被调用时采取相应的行动。

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

          【讨论】:

          • 你忘了包含你的方法“calculateKeyboardOffsetWithHeight:”,没有它这将不起作用
          • @Adam 我认为不需要该方法,但我可以看到它如何引起混乱,因此我将其添加并解释了它。我希望这会有所帮助。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-30
          相关资源
          最近更新 更多