Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid keyboard hide & show when focus changes from UITextField and UIWebView?

I have a requirement in which the view contains one native UITextField and one UIWebView. The issue is if I switch the focus from UITextView to UIWebView, the keyboard window flicker(hides and then shows). ie, I got UIKeyboardWillHideNotification and UIKeyboardDidShowNotification

But, this is not happening when I switch the other way. ies, I got only UIKeyboardDidShowNotification

Is there any way to avoid this flickering effect?

Note: I also notices if I have multiple UITextField and UIWebView, this issue is not happening with the same type of views.

like image 534
ManojMarathayil Avatar asked Aug 03 '13 09:08

ManojMarathayil


People also ask

How do I make my keyboard always visible?

You must have an EditText in your layout and that need to extent EditText base class. then Override onKeyPreIme() method, and return True. Now your keyboard will be always visible and can't be dismissed by Back key.

Why is my touch keyboard not popping up?

Right-click the Start button and select Settings. Go to Ease of Access > Keyboard. Turn on the toggle below Use the On-Screen Keyboard.


1 Answers

I've solved this problem through the code below. Simply set webView.usesGUIFixes = YES; and it should solve your problem. The code below also lets you set a custom input view to use for the UIWebView keyboard:

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
like image 119
diegoreymendez Avatar answered Sep 27 '22 16:09

diegoreymendez