it-swarm.com.ru

Определить момент начала новой строки в UITextView

Я пытаюсь определить, когда каретка переходит на новую строку в UITextView. Я могу определить это путем сравнения общей ширины позже с шириной UITextView:

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

Но это не работает должным образом, потому что -sizeWithAttributes:textView возвращает только ширину букв без отступа. Помогите пожалуйста решить это.

14
mriddi

Вот как я бы это сделал:

  • Получить UITextPosition последнего символа.
  • Позвоните caretRectForPosition на ваш UITextView.
  • Создайте переменную CGRect и изначально сохраните в ней CGRectZero.
  • В вашем методе textViewDidChange: вызовите caretRectForPosition:, передав UITextPosition.
  • Сравните его с текущим значением, хранящимся в переменной CGRect. Если новый y-Origin элемента caretRect больше последнего, это означает, что достигнута новая строка.

Образец кода:

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здесь . Это волшебно, я говорю вам.

Дайте мне знать, если у вас есть другие проблемы с этим.

26
n00bProgrammer

Для 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

    }
7
Sourav Gupta

ответ @ n00bProgrammer в Swift-4 сточнееобнаружение разрыва строки. 

@ n00bProgrammer ответ идеален, за исключением того, что он реагирует по-разному, когда пользователь начинает вводить в первой строке, он также представляет Started New Line.
Преодоление проблемы, вот улучшенный код

    var previousRect = CGRect.zero
    func textViewDidChange(_ textView: UITextView) {
        let pos = textView.endOfDocument
        let currentRect = textView.caretRect(for: pos)
        self.previousRect = self.previousRect.Origin.y == 0.0 ? currentRect : previousRect
        if(currentRect.Origin.y > previousRect.Origin.y){
            //new line reached, write your code
            print("Started New Line")
        }
        previousRect = currentRect
    }
5
Kiran Jasvanee

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
user2359168

Вы можете использовать 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;
}
3
Stuart Campbell

Вам нужно получить высоту текста, а не ширину. Используйте sizeWithFont:constrainedToSize:lineBreakMode: (если вам нужно поддерживать iOS 6 или более раннюю версию) или boundingRectWithSize:options:attributes:context:, если вы поддерживаете только iOS 7.

0
rmaddy

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
    }
}
0
Carson Vo