UITextView плавающий синий прямоугольник при прокрутке

У меня UITextView с отключенной прокруткой. Это внутри UIScrollView. Если я наберу "fffs", появится * маленькая синяя рамка. Если я прокручиваю, пока отображается это окно, оно не исчезает, оно просто ** плавает по экрану и выглядит как очевидная ошибка.

Если я использую UITextView с включенной прокруткой, окно скрывается, как только UITextView начинает прокручиваться. Я предполагаю, что UITextView перехватывает события прокрутки своих собственных полос прокрутки, когда он их имеет, и скрывает это поле при прокрутке. Этого не происходит, когда он находится внутри какого-то другого UIScrollView, поэтому мне, вероятно, нужно сделать это самому, но как мне заставить его скрыть этот блок (и, возможно, все остальное, что обычно делает, например, применить автокоррекцию) - в надежный и не приватный способ API?

Я мог бы подать ошибку в Apple, но в то же время я надеюсь, что у кого-то есть быстрое решение.

* маленькая синяя рамка = автокоррекция / выделение - не знаю точно, как его назвать, возможно, поэтому я не смог найти ни одного существующего ответа.

** плавает = думаю, отображение: исправлено в CSS

Обновить:

Я попробовал это и некоторые другие варианты этого, внутри scrollViewWillBeginDragging:

UITextView *tv = GetFirstResponder(); // confirmed this returns correct value
tv.autocorrectionType = UITextAutocorrectionTypeNo;
[tv setNeedsDisplay];
[tv setNeedsLayout];
[tv setNeedsUpdateConstraints]; // just for giggles?

Я подтвердил, что код работает, и я даже не удосужился добавить код для повторного включения автокоррекции, поэтому я знаю, что он не включается снова. Я также могу подтвердить, что он несколько "работает", потому что когда я щелкаю по другому полю, а затем возвращаюсь к исходному полю, автокоррекция теперь отключена.

Я думаю, если бы я мог найти UIView для этой маленькой синей рамки, я мог бы спрятать / удалить ее. Я попытался использовать новый View Debugging в XCode, но он не захватывает синий прямоугольник, поэтому он должен быть особенным.

При том, что все люди используют UITextView таким же образом, как и я (изменяйте размер при вводе, никакой внутренней прокрутки), я удивлен, что никто еще не понял этого. Если это не новая ошибка, я использую последнюю версию iOS и оба моих тестовых устройства (iPod 5 и iPad).

3 ответа

Решение

Кажется, пока это работает, но я еще не провел тонны тестирования:

-(void) walkViews:(UIView*)v
{
    NSString *className = NSStringFromClass([v class]);
    if([className isEqualToString:@"UIAutocorrectInlinePrompt"])
        v.hidden = YES;
    NSArray *subviews = v.subviews;
    for(UIView *sv in subviews)
        [self walkViews:sv];
}

-(void) scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSArray *windows = [UIApplication sharedApplication].windows;
    for (UIWindow *w in windows)
    {
        [self walkViews:w];
    }
}

Возможно, вы бы хотели получить более подходящее название для "walkViews", но в основном, когда прокручивается UIScrollView, я нахожу представление "маленького синего прямоугольника" и скрываю его. Пока что мое ограниченное тестирование, коробка вернется, если я начну печатать снова, и это необходимо. Похоже, что это не мешает другим функциям автокоррекции. Все еще хак, и с учетом всех проблем, которые идут с этим типом вещи, но пока Apple не сможет исправить эту ошибку, я, вероятно, буду использовать этот обходной путь.

Попробуйте установить его autocorrectionType в UITextAutocorrectionTypeNo,

Это похоже на проблему Apple. В качестве обходного пути вы можете автоматически отклонить запрос автокоррекции при запуске прокрутки, как показано ниже.

Примечание 1: Написано на Xamarin, но легко переведено на цель-C.

Примечание 2: метод отклонения запроса автозамены взят здесь.

Примечание 3: вы можете найти метод FindFirstResponder() здесь.

public override void ViewDidAppear(bool animated)
{
    base.ViewDidAppear(animated);

    scrollView.DraggingStarted += scrollView_DraggingStarted;
}

public override void ViewWillDisappear(bool animated)
{
   scrollView.DraggingStarted -= scrollView_DraggingStarted;

    base.ViewWillDisappear(animated);
}

void scrollView_DraggingStarted(object sender, EventArgs e)
{
    UIView activeView = FindFirstResponder(View);
    if (activeView != null)
    {
        UITextView activeTextView = activeView as UITextView;
        if (activeTextView != null)
        {
            RejectAutocorrectPrompt(activeTextView);
        }
    }
}

private void RejectAutocorrectPrompt(UITextView textView)
{
    string originalText = textView.Text;
    NSRange originalRange = textView.SelectedRange;
    CGPoint originalOffset = textView.ContentOffset;

    //Force any pending autocorrection to be applied
    textView.ResignFirstResponder();
    textView.BecomeFirstResponder();

    string finalText = textView.Text;
    if (originalText != finalText)
    {
        textView.Text = originalText;
        textView.SelectedRange = originalRange;
        textView.SetContentOffset(originalOffset, false);
    }
}
Другие вопросы по тегам