UITextView cursor below frame when changing frame

前端 未结 9 441
名媛妹妹
名媛妹妹 2020-12-01 06:50

I have a UIViewCOntrollerthat contains a UITextView. When the keyboard appears I resize it like this:

#pragma mark - Responding to          


        
9条回答
  •  一整个雨季
    2020-12-01 07:33

    For those that have a UITextView inside a UIScrollView where iOS < 7 took care of scrolling the caret into view: Here's how it works with iOS 7 (and also 5 & 6).

    // This is the scroll view reference
    @property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
    
    // Track the current UITextView
    @property (weak, nonatomic) UITextView *activeField;
    
    - (void)textViewDidBeginEditing:(UITextView *)textView
    {
        self.activeField = textView;
    }
    
    - (void)textViewdDidEndEditing:(UITextView *)textView
    {
        self.activeField = nil;
    }
    
    // Setup the keyboard observers that take care of the insets & initial scrolling
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];
    
    - (void)keyboardWasShown:(NSNotification*)aNotification
    {
        // Set the insets above the keyboard
        NSDictionary* info = [aNotification userInfo];
        CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    
        UIEdgeInsets insets = self.vForm.contentInset;
        insets.bottom += kbSize.height;
        self.vForm.contentInset = insets;
    
        insets = self.vForm.scrollIndicatorInsets;
        insets.bottom += kbSize.height;
        self.vForm.scrollIndicatorInsets = insets;
    
        // Scroll the active text field into view
        CGRect aRect = self.vForm.frame;
        aRect.size.height -= kbSize.height;
        CGPoint scrollPoint = CGPointMake(0.0, self.activeField.frame.origin.y);
        [self.scrollView setContentOffset:scrollPoint animated:YES];
    }
    
    - (void)keyboardWillBeHidden:(NSNotification*)aNotification
    {
        UIEdgeInsets contentInsets = UIEdgeInsetsZero;
        self.vForm.contentInset = contentInsets;
        self.vForm.scrollIndicatorInsets = contentInsets;
    }
    
    // This is where the magic happens. Set the class with this method as the UITextView's delegate.
    - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
        // Scroll the textview to the caret position
        [textView scrollRangeToVisible:textView.selectedRange];
    
        // Scroll the scrollview to the caret position within the textview
        CGRect targetRect = [textView caretRectForPosition:textView.selectedTextRange.end];
        targetRect.origin.y += self.activeField.frame.origin.y;
        [self.scrollView scrollRectToVisible:targetRect animated:YES];
    
        return YES;
    }
    

    I tried to include most of the required glue code. The only things missing are setting the UITextView's delegate and dismissing the keyboard.

    Took 2-3 days to figure out what previously worked. Thanks, Apple.

提交回复
热议问题