【问题标题】:How to avoid keyboard hide & show when focus changes from UITextField and UIWebView?当焦点从 UITextField 和 UIWebView 更改时,如何避免键盘隐藏和显示?
【发布时间】:2013-08-03 09:13:07
【问题描述】:

我有一个要求,其中视图包含一个本机 UITextField 和一个 UIWebView。问题是如果我将焦点从 UITextView 切换到 UIWebView,键盘窗口会闪烁(隐藏然后显示)。 即,我得到了 UIKeyboardWillHideNotification 和 UIKeyboardDidShowNotification

但是,当我换另一种方式时,这不会发生。也就是,我只有 UIKeyboardDidShowNotification

有什么办法可以避免这种闪烁效果?

注意:我还注意到,如果我有多个 UITextField 和 UIWebView,相同类型的视图不会出现此问题。

【问题讨论】:

  • 嘿,你想在从 webView 切换到 UITextView 时显示键盘吗?
  • 不完全是。当焦点位于 UITextView 中时,键盘显示。现在我将焦点切换到 UIWebView。此时会闪烁。
  • 焦点,是指点击吗?
  • 是的,我的意思是在 webview html 中点击 contenteditable 字段/文本字段。
  • 所以当你在 textView 外部点击时,你想让键盘关闭吗?

标签: ios objective-c


【解决方案1】:

我已经通过下面的代码解决了这个问题。只需设置webView.usesGUIFixes = YES; 即可解决您的问题。下面的代码还允许您设置自定义输入视图以用于 UIWebView 键盘:

UIWebView+GUIFixes.h

#import <UIKit/UIKit.h>

@interface UIWebView (GUIFixes)

/**
 *  @brief      The custom input accessory view.
 */
@property (nonatomic, strong, readwrite) UIView* customInputAccessoryView;

/**
 *  @brief      Wether the UIWebView will use the fixes provided by this category or not.
 */
@property (nonatomic, assign, readwrite) BOOL usesGUIFixes;

@end

UIWebView+GUIFixes.m

#import "UIWebView+GUIFixes.h"
#import <objc/runtime.h>

@implementation UIWebView (GUIFixes)

static const char* const kCustomInputAccessoryView = "kCustomInputAccessoryView";
static const char* const fixedClassName = "UIWebBrowserViewMinusAccessoryView";
static Class fixClass = Nil;

- (UIView *)browserView
{
    UIScrollView *scrollView = self.scrollView;

    UIView *browserView = nil;
    for (UIView *subview in scrollView.subviews) {
        if ([NSStringFromClass([subview class]) hasPrefix:@"UIWebBrowserView"]) {
            browserView = subview;
            break;
        }
    }

    return browserView;
}

- (id)methodReturningCustomInputAccessoryView
{
    UIView* view = [self performSelector:@selector(originalInputAccessoryView) withObject:nil];

    if (view) {

        UIView* parentWebView = self.superview;

        while (parentWebView && ![parentWebView isKindOfClass:[UIWebView class]])
        {
            parentWebView = parentWebView.superview;
        }

        UIView* customInputAccessoryView = [(UIWebView*)parentWebView customInputAccessoryView];

        if (customInputAccessoryView) {
            view = customInputAccessoryView;
        }
    }

    return view;
}

- (BOOL)delayedBecomeFirstResponder
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [super becomeFirstResponder];
    });

    return YES;
}

- (void)ensureFixedSubclassExistsOfBrowserViewClass:(Class)browserViewClass
{
    if (!fixClass) {
        Class newClass = objc_allocateClassPair(browserViewClass, fixedClassName, 0);
        IMP oldImp = class_getMethodImplementation(browserViewClass, @selector(inputAccessoryView));
        class_addMethod(newClass, @selector(originalInputAccessoryView), oldImp, "@@:");

        IMP newImp = [self methodForSelector:@selector(methodReturningCustomInputAccessoryView)];
        class_addMethod(newClass, @selector(inputAccessoryView), newImp, "@@:");
        objc_registerClassPair(newClass);

        IMP delayedFirstResponderImp = [self methodForSelector:@selector(delayedBecomeFirstResponder)];
        Method becomeFirstResponderMethod = class_getInstanceMethod(browserViewClass, @selector(becomeFirstResponder));
        method_setImplementation(becomeFirstResponderMethod, delayedFirstResponderImp);

        fixClass = newClass;
    }
}

- (BOOL)usesGUIFixes
{
    UIView *browserView = [self browserView];
    return [browserView class] == fixClass;
}

- (void)setUsesGUIFixes:(BOOL)value
{
    UIView *browserView = [self browserView];
    if (browserView == nil) {
        return;
    }

    [self ensureFixedSubclassExistsOfBrowserViewClass:[browserView class]];

    if (value) {
        object_setClass(browserView, fixClass);
    }
    else {
        Class normalClass = objc_getClass("UIWebBrowserView");
        object_setClass(browserView, normalClass);
    }

    [browserView reloadInputViews];
}

- (UIView*)customInputAccessoryView
{
    return objc_getAssociatedObject(self, kCustomInputAccessoryView);
}

- (void)setCustomInputAccessoryView:(UIView*)view
{
    objc_setAssociatedObject(self,
                             kCustomInputAccessoryView,
                             view,
                             OBJC_ASSOCIATION_RETAIN);
}

@end

【讨论】:

  • 让你们知道。我们最终将 UITextField 作为单独的 contentEditable div 移动到 Web 视图中。这解决了键盘隐藏问题,无需此解决方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
  • 2015-08-10
  • 2011-05-21
  • 2022-11-16
相关资源
最近更新 更多