UITextView floating blue box when scrolling

2019-07-23 18:14发布

I have a UITextView with scrolling disabled. It is inside a UIScrollView. If I type "fffs" a *little blue box appears. If I scroll while that box is displayed, the box doesn't disappear, it just **floats over the display and looks like an obvious bug.

If I use UITextView with scrolling enabled, the box is hidden as soon as the UITextView starts to scroll. I assume UITextView hooks the scroll events of its own scrollbars, when it has them, and hides that box when it scrolls. This doesn't happen when it is inside some other UIScrollView, so I probably need to do that myself, but how do I get it to hide that box (and maybe anything else it normally does like apply the auto-correction) -- in a robust and non-private API way?

I might file a bug with Apple, but in the meantime I'm hoping someone has a quick fix.

*little blue box = the auto-correct box/highlight thing -- not sure exactly what to call it, maybe why I couldn't find any existing answers.

**floats = think display:fixed in CSS

Update:

I tried this and some other variations of this, inside scrollViewWillBeginDragging:

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

I confirmed the code is running, and I didn't even bother adding code to re-enable auto-correction yet, so I know it isn't being turned back on. I can also confirm it is "working" somewhat because when I click to another field, then back to the original field, auto-correct is now disabled.

I'm thinking if I could locate the UIView for that little blue box, I could hide/remove it. I tried using the new View Debugging in XCode, but it doesn't capture the blue box, so it must be special.

With all of the people using UITextView in a similar way that I am (resize as you type, no internal scrolling), I'm surprised nobody has figured this out yet. Unless it's a brand-new bug, I am using the latest iOS version and both of my test devices (iPod 5 and iPad).

3条回答
聊天终结者
2楼-- · 2019-07-23 18:33

This seems to be an Apple issue. As a workaround, you can automatically reject the autocorrection prompt when you start scrolling, as below.

Note 1: Written in Xamarin, but easily translated to objective-C.

Note 2: The method for rejecting the autocorrect prompt was taken from here.

Note 3: You can find the FindFirstResponder() method here.

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);
    }
}
查看更多
疯言疯语
3楼-- · 2019-07-23 18:47

This seems to work so far, but I haven't done a ton of testing yet:

-(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];
    }
}

You'd probably want a better name for "walkViews", but basically when the UIScrollView scrolls, I locate the view for the "little blue box" and hide it. So far, my limited testing, the box does come back if I start typing again and it is needed. It doesn't seem to mess up any other auto-correct features either. Still a hack, and subject to all of the issues that comes with that type of thing, but until Apple can fix this bug, I'll probably use this work-around.

查看更多
爷、活的狠高调
4楼-- · 2019-07-23 18:55

Try setting its autocorrectionType to UITextAutocorrectionTypeNo.

查看更多
登录 后发表回答