Detect moment when newline starts in UITextView

后端 未结 8 855
甜味超标
甜味超标 2020-12-08 16:23

I try to detect when carriage goes at new line in UITextView. I can detect it by comparison total later width with UITextView width:

CGSize size = [textView.         


        
相关标签:
8条回答
  • 2020-12-08 16:50

    SWIFT 4

    If you don't want to use previousRect. Let's try this:

    func textViewDidChange(_ textView: UITextView) {
        let pos = textView.endOfDocument
        let currentRect = textView.caretRect(for: pos)
        if (currentRect.origin.y == -1 || currentRect.origin.y == CGFloat.infinity){
           print("Yeah!, I've gone to a new line") 
           //-1 for new line with a char, infinity is new line with a space
        }
    }
    
    0 讨论(0)
  • 2020-12-08 16:56

    You need to get the height of the text, not the width. Use either sizeWithFont:constrainedToSize:lineBreakMode: (if you need to support iOS 6 or earlier) or use boundingRectWithSize:options:attributes:context: if you only support iOS 7.

    0 讨论(0)
  • 2020-12-08 17:02

    Swift 3

    The accepted answer and the swift version works fine, but here is a Swift 3 version for the lazy people out there.

    class CustomViewController: UIViewController, UITextViewDelegate {
    
        let textView = UITextView(frame: .zero)
        var previousRect = CGRect.zero
    
        override func viewDidLoad(){
            textView.frame = CGRect(
                x: 20, 
                y: 0, 
                width: view.frame.width, 
                height: 50
            )
            textView.delegate = self
            view.addSubview(textView)
        }
    
        func textViewDidChange(_ textView: UITextView) {
            let pos = textView.endOfDocument
            let currentRect = textView.caretRect(for: pos)
            if previousRect != CGRect.zero {
                if currentRect.origin.y > previousRect.origin.y {
                    print("new line")
                }
            }
            previousRect = currentRect
        }
    }
    
    0 讨论(0)
  • 2020-12-08 17:06

    You can use the UITextViewDelegate

    - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText: (NSString *)text
    {
         BOOL newLine = [text isEqualToString:@"\n"];
         if(newLine)
         {
              NSLog(@"User started a new line");
         }
         return YES;
    }
    
    0 讨论(0)
  • 2020-12-08 17:07

    SWIFT 5

    Lets not overcomplicate things.

        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    
        if text == "\n" {
            // return pressed
        }
    }
    
    0 讨论(0)
  • 2020-12-08 17:09

    This is how I would do it:

    • Get the UITextPosition of the last character.
    • Call caretRectForPosition on your UITextView.
    • Create a CGRect variable and initially store CGRectZero in it.
    • In your textViewDidChange: method, call caretRectForPosition: by passing the UITextPosition.
    • Compare it with the current value stored in the CGRect variable. If the new y-origin of the caretRect is greater than the last one, it means a new line has been reached.

    Sample code:

    CGRect previousRect = CGRectZero;
    - (void)textViewDidChange:(UITextView *)textView{
    
        UITextPosition* pos = yourTextView.endOfDocument;//explore others like beginningOfDocument if you want to customize the behaviour
        CGRect currentRect = [yourTextView caretRectForPosition:pos];
    
        if (currentRect.origin.y > previousRect.origin.y){
                //new line reached, write your code
            }
        previousRect = currentRect;
    
    }
    

    Also, you should read the documentation for UITextInput protocol reference here. It is magical, I'm telling you.

    Let me know if you have any other issues with this.

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