检测新行在UITextView中启动的时刻

时间:2013-11-15 19:07:47

标签: ios objective-c nsstring uitextview

我尝试在UITextView中检测托架何时进入新行。我可以通过比较总后来宽度和UITextView宽度来检测它:

CGSize size = [textView.text sizeWithAttributes:textView.typingAttributes];
if(size.width > textView.bounds.size.width)
      NSLog (@"New line");

但它不能正常工作,因为-sizeWithAttributes:textView只返回没有缩进宽度的字母宽度。请帮忙解决这个问题。

8 个答案:

答案 0 :(得分:28)

我就是这样做的:

  • 获取最后一个角色的UITextPosition
  • caretRectForPosition
  • 上致电UITextView
  • 创建一个CGRect变量,最初将CGRectZero存储在其中。
  • textViewDidChange:方法中,传递caretRectForPosition:来致电UITextPosition
  • 将其与CGRect变量中存储的当前值进行比较。如果caretRect的新y-origin大于最后一个,则表示已到达新行。

示例代码:

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;

}

另外,您应该阅读UITextInput协议参考here的文档。这是神奇的,我告诉你。

如果您对此有任何其他问题,请与我们联系。

答案 1 :(得分:8)

对于Swift使用此

previousRect = CGRectZero

 func textViewDidChange(textView: UITextView) {

        var pos = textView.endOfDocument
        var currentRect = textView.caretRectForPosition(pos)
        if(currentRect.origin.y > previousRect?.origin.y){
            //new line reached, write your code
        }
        previousRect = currentRect

    }

答案 2 :(得分:5)

回答<{>}中的 @ n00bProgrammer 更准确 换行检测。

@ n00bProgrammer 答案是完美的,只有当用户开始输入第一行时它会有不同的反应,它也会显示Swift-4克服问题,这里是精炼代码

Started New Line

答案 3 :(得分:4)

Swift 3

接受的答案和swift版本工作正常,但这里有一个Swift 3版本,供那些懒惰的人使用。

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

答案 4 :(得分:3)

您可以使用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;
}

答案 5 :(得分:0)

您需要获取文本的高度,而不是宽度。如果您只支持iOS 7,请使用sizeWithFont:constrainedToSize:lineBreakMode:(如果您需要支持iOS 6或更早版本)或使用boundingRectWithSize:options:attributes:context:

答案 6 :(得分:0)

SWIFT 4

如果您不想使用previousRect。让我们尝试一下:

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

答案 7 :(得分:0)

SWIFT 5

不要让事情变得过于复杂。

    func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {

    if text == "\n" {
        // return pressed
    }
}