16

Is it possible to remove the form assistant from the iPhone popup keyboard in a standalone web app? I know the general consensus is that it's not possible in Mobile Safari, but a standalone app runs in a UIWebView, and functions differently in several ways (example), so I'm hoping this might be possible.

You can see it here right above the keyboard:

enter image description here

The Previous and Next buttons cycle between <form> inputs. But I have a single <input> element, so they are disabled. The Done button hides the keyboard, but since I have a height-flexible <ul> (that takes up the space between the keyboard and the <input>), and I have nothing else on this page, it serves no purpose.

On a tiny screen, and with almost half the screen taken up by the keyboard, the 44 pixels that make up this toolbar are a huge waste of space (an entire <li>'s worth).

Native iOS apps can remove it, so I know it's at least possible on the phone, I've just not discovered a way to do it in a web app. This is from the Facebook app and the page is very similar to mine:

enter image description here

I've tried using an <input> not wrapped in a <form> and also using a contenteditable <div>, but the results were the same. There are several custom -webkit- styles to control various aspects of the web app interface, but they are poorly documented, and a search turned up nothing on this.

Any way to remove the form assistant in a web app?

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239

3 Answers3

12

If you app is a web app wrapped in a native Objetive-C app this is possible by manipulating Keyboard views.

first, register to receive the keyboardDidShow notification:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];

this will call the following method when keyboard shows up:

-(void)keyboardDidShow:(NSNotification*)notif
{
    NSArray *array = [[UIApplication sharedApplication] windows];

    for (UIWindow* wind in array) {
        for (UIView* currView in wind.subviews) {
            if ([[currView description] hasPrefix:@"<UIPeripheralHostView"]) {
                for (UIView* perView in currView.subviews) {
                    if ([[perView description] hasPrefix:@"<UIWebFormAccessory"]) {
                        [perView setHidden:YES];
                    }
                }

            }
        }
    }
}

this method goes over the views on screen looking for the form assistant and hiding it.

NOTE: Apple probably won't reject this, as i've seen it being used by Facebook etc, but this technique might break in upcoming iOS releases.

Jorge Cohen
  • 1,512
  • 10
  • 34
  • I am wrapping my app in a UIWebView for the final product, but have done everything "pre-wrap", so far. It looks like this may be the only solution to this problem though. – ThinkingStiff Jan 29 '12 at 18:29
  • Use `UIKeyboardWillShowNotification` instead of `UIKeyboardDidShowNotification` then you don't see the bar appear and then disappear again... – Besi Jul 17 '12 at 15:50
  • You should also do this `[perView removeFromSuperview];` otherwise the hidden view will swallow any touches and not pass them to the underlying `UIWebView` – Besi Jul 18 '12 at 18:48
  • @Besi that's wrong. UIKeyboardWillShowNotification is not working since the views are not instantiated before the keyboard appears. – The dude Aug 07 '12 at 08:34
  • 1
    @Besi it doesn't work for me either. By the way, I found a better version of the solution that @HeziCohen proposed. It can be found [here](http://stackoverflow.com/questions/13143689/how-to-find-uiwebview-toolbar-to-replace-them-on-ios-6#13146681). That solution uses `UIKeyboardWillShowNotification` instead of `UIKeyboardDidShowNotification` (and it works) and, furthermore, gets rid of the gray horizontal line that remains after the form assistant bar is removed. – Alexander Poleschuk Jun 14 '13 at 21:03
5

All signs point to this not being possible, including several questions here.

Community
  • 1
  • 1
seth.miller
  • 1,988
  • 17
  • 23
  • Those are all related to mobile Safari not in standalone mode. This is for a chrome-less web app. I'm hoping there is more control, but perhaps not. – ThinkingStiff Jan 27 '12 at 01:12
  • Unfortunately I don't believe you get control over that with a chromeless app. Maybe someone will prove me wrong, though. – seth.miller Jan 27 '12 at 01:30
  • Any updated solutions for iOS 9.3.2? or is it still impossible? – reectrix Jun 29 '16 at 18:42
1

You can do a category of UIView and "override" the behaviour of addSubview: like the example below. Call the method "exachangeMethods" from your applicationDidFinishLaunching of your AppDelegate.

#import "UIView+util.h"
#import <objc/runtime.h>

@implementation UIView (util)

// Swaps our custom implementation with the default one
// +load is called when a class is loaded into the system
+ (void) exchangeMethods
{
    SEL origSel = @selector(addSubview:);

    SEL newSel = @selector(customAddSubview:);

    Class viewClass = [UIView class];

    Method origMethod = class_getInstanceMethod(viewClass, origSel);
    Method newMethod = class_getInstanceMethod(viewClass, newSel);
    method_exchangeImplementations(origMethod, newMethod);
}
- (void) customAddSubview:(UIView *)view{

    if( [[view description]rangeOfString:@"<UIWebFormAccessory"].location!=NSNotFound) {
        return;
    }

    // This line at runtime does not go into an infinite loop
    // because it will call the real method instead of ours.
    return [self customAddSubview:view];

}

@end
noripcord
  • 3,412
  • 5
  • 29
  • 26