UITextView cursor below frame when changing frame

前端 未结 9 461
名媛妹妹
名媛妹妹 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:24

    Anders and Leo Natan have great solutions. However, I needed to modify their answers a little to get the scrolling to work properly with contentInset. The problem I faced was that textViewDidBeginEditing: gets called before keyboardWasShown: so the contentInset change does not get reflected the first time through. Here is what I did:

    In .h

    @interface NoteDayViewController : UIViewController 
    {
        UIEdgeInsets noteTextViewInsets;
        UIEdgeInsets noteTextViewScrollIndicatorInsets;
        CGRect oldRect;
        NSTimer *caretVisibilityTimer;
        float noteViewBottomInset;
    }
    @property (weak, nonatomic) IBOutlet UITextView *noteTextView;
    

    In .m

    - (void)registerForKeyboardNotifications
    {
        [[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
    {
        CGFloat kbHeight = // get the keyboard height following your usual method
    
        UIEdgeInsets contentInsets = noteTextViewInsets;
        contentInsets.bottom = kbHeight;
        noteTextView.contentInset = contentInsets;
    
        UIEdgeInsets scrollInsets = noteTextViewScrollIndicatorInsets;
        scrollInsets.bottom = kbHeight;
        noteTextView.scrollIndicatorInsets = scrollInsets;
    
        [noteTextView setNeedsDisplay];
    }
    
    - (void)keyboardWillBeHidden:(NSNotification*)aNotification
    {    
        noteTextView.contentInset = noteTextViewInsets;
        noteTextView.scrollIndicatorInsets = noteTextViewScrollIndicatorInsets;   
        [noteTextView setNeedsDisplay];
    }
    
    - (void)textViewDidBeginEditing:(UITextView *)textView
    {
        oldRect = [noteTextView caretRectForPosition:noteTextView.selectedTextRange.end];
        noteViewBottomInset = noteTextView.contentInset.bottom;
        caretVisibilityTimer = [NSTimer scheduledTimerWithTimeInterval:0.3 target:self selector:@selector(scrollCaretToVisible) userInfo:nil repeats:YES];
    }
    
    - (void)textViewDidEndEditing:(UITextView *)textView
    {
        [caretVisibilityTimer invalidate];
        caretVisibilityTimer = nil;
    }
    
    - (void)scrollCaretToVisible
    {
        // This is where the cursor is at.
        CGRect caretRect = [noteTextView caretRectForPosition:noteTextView.selectedTextRange.end];
    
        // test if the caret has moved OR the bottom inset has changed
        if(CGRectEqualToRect(caretRect, oldRect) && noteViewBottomInset == noteTextView.contentInset.bottom)
        return;
    
        // reset these for next time this method is called
        oldRect = caretRect;
        noteViewBottomInset = noteTextView.contentInset.bottom;
    
        // this is the visible rect of the textview.
        CGRect visibleRect = noteTextView.bounds;
        visibleRect.size.height -= (noteTextView.contentInset.top + noteTextView.contentInset.bottom);
        visibleRect.origin.y = noteTextView.contentOffset.y;
    
        // We will scroll only if the caret falls outside of the visible rect.
        if (!CGRectContainsRect(visibleRect, caretRect))
        {
            CGPoint newOffset = noteTextView.contentOffset;
            newOffset.y = MAX((caretRect.origin.y + caretRect.size.height) - visibleRect.size.height, 0);
            [noteTextView setContentOffset:newOffset animated:NO]; // must be non-animated to work, not sure why
        }
    }
    

提交回复
热议问题