Обнаруживать момент запуска новой строки в UITextView
Я пытаюсь обнаружить, когда каретка идет по новой строке в UITextView. Я могу обнаружить его путем сравнения общей ширины позже с шириной UITextView:
CGSize size = [textView.text sizeWithAttributes:textView.typingAttributes];
if(size.width > textView.bounds.size.width)
NSLog (@"New line");
Но доза не работает должным образом, потому что -sizeWithAttributes:textView
возвращает только ширину букв без ширины отступа. Помогите решить эту проблему.
Ответы
Ответ 1
Вот как я бы это сделал:
- Получить
UITextPosition
последнего символа. - Вызовите
caretRectForPosition
для вашего UITextView
. - Создайте переменную
CGRect
и изначально сохраните в ней CGRectZero
. - В вашем
textViewDidChange:
метод вызовите caretRectForPosition:
путем передачи UITextPosition
. - Сравните его с текущим значением, хранящимся в переменной
CGRect
. Если новый y-источник элемента 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
протокол UITextInput
здесь. Это волшебно, я говорю вам.
Дайте мне знать, если у вас есть другие проблемы с этим.
Ответ 2
Для 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
}
Ответ 3
ответ @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 : self.previousRect
if currentRect.origin.y > self.previousRect.origin.y {
//new line reached, write your code
print("Started New Line")
}
self.previousRect = currentRect
}
Ответ 4
Swift 3
Принятый ответ и быстрая версия работают нормально, но вот версия 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
}
}
Ответ 5
Вы можете использовать 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;
}
Ответ 6
Вам нужно получить высоту текста, а не ширину. Используйте либо sizeWithFont:constrainedToSize:lineBreakMode:
(если вам нужно поддерживать iOS 6 или ранее), либо используйте boundingRectWithSize:options:attributes:context:
, если вы поддерживаете только iOS 7.
Ответ 7
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
}
}