Reputation: 187014
I want to get rid of the bar on top of the keyboard that appears when you focus a text field in a webview. We have some other ways of handling this and it's redundant and unnecessary.
webview keyboard bar http://beautifulpixel.com/assets/iPhone_Simulator-20100120-152330.png
If you hit this problem, make sure to head over to https://bugreport.apple.com and duplicate rdar://9844216
Upvotes: 18
Views: 12414
Reputation: 167
this code definetly works for me... hope this also works for you.
- (void)viewDidLoad{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
[self performSelector:@selector(removeBar) withObject:nil afterDelay:0];
}
- (void)removeBar {
// Locate non-UIWindow.
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual:[UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIWebFormView
for (UIView *possibleFormView in [keyboardWindow subviews]) {
if ([[possibleFormView description] hasPrefix:@"<UIPeripheralHostView"]) {
for (UIView* peripheralView in [possibleFormView subviews]) {
// hides the backdrop (iOS 7)
if ([[peripheralView description] hasPrefix:@"<UIKBInputBackdropView"]) {
//skip the keyboard background....hide only the toolbar background
if ([peripheralView frame].origin.y == 0){
[[peripheralView layer] setOpacity:0.0];
}
}
// hides the accessory bar
if ([[peripheralView description] hasPrefix:@"<UIWebFormAccessory"]) {
// remove the extra scroll space for the form accessory bar
UIScrollView *webScroll;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 5.0) {
webScroll = [[self webviewpot] scrollView];
} else {
webScroll = [[[self webviewpot] subviews] lastObject];
}
CGRect newFrame = webScroll.frame;
newFrame.size.height += peripheralView.frame.size.height;
webScroll.frame = newFrame;
// remove the form accessory bar
[peripheralView removeFromSuperview];
}
// hides the thin grey line used to adorn the bar (iOS 6)
if ([[peripheralView description] hasPrefix:@"<UIImageView"]) {
[[peripheralView layer] setOpacity:0.0];
}
}
}
}
}
Upvotes: 1
Reputation: 4924
There are no public APIs for doing this. You could remove it by examining the view hierarchy and removing the view as some have suggested, but this would be very risky.
Here's why it's a bad idea:
If Apple doesn't have an official API for removing the bar, they may have good reasons for doing so, and their own code may rely on it being there. You might not ever encounter a problem because you do all your testing (for example) on an English keyboard. But what if the view you are removing is required for entry in another language, or for accessibility purposes? Or what if in a future version of iOS their own implementation changes such that it assumes the view is always there? Your code will crash, and you'll be stuck scrambling to get an update out while frustrated users wait for weeks.
Interestingly, Remco's appended answer proves this point. On iOS 6.0.1, a change was made that required a fix to the hack. Anyone who had implemented the hack for ios 5 would have been forced to do an update as a result. Fortunately it was only an aesthetic change, but it could have been much worse.
Upvotes: 3
Reputation: 134
This is an addition to Yun's answer. On iOS6 (6.0.1) there might be a horizontal grey border or shadow line on top of the row where the accessory (previous / next / done) used to be before it was removed. This fix works for me, and I'd like to share. Curious to hear if it works for you as well.
To remove the border, I added this code to the inner loop of removeBar():
if ([[subviewWhichIsPossibleFormView description] rangeOfString:@"UIImageView"].location != NSNotFound) {
[[subviewWhichIsPossibleFormView layer] setOpacity: 0.0];
}
We need to add the QuartzCore framework to the head of the .m file, so we can set the opacity of the layer involved.
So, we get:
...
#import <QuartzCore/QuartzCore.h>
...
- (void)removeBar {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual:[UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
for (UIView *possibleFormView in [keyboardWindow subviews]) {
// iOS 5 sticks the UIWebFormView inside a UIPeripheralHostView.
if ([[possibleFormView description] rangeOfString:@"UIPeripheralHostView"].location != NSNotFound) {
for (UIView *subviewWhichIsPossibleFormView in [possibleFormView subviews]) {
if ([[subviewWhichIsPossibleFormView description] rangeOfString:@"UIWebFormAccessory"].location != NSNotFound) {
[subviewWhichIsPossibleFormView removeFromSuperview];
}
// iOS 6 leaves a grey border / shadow above the hidden accessory row
if ([[subviewWhichIsPossibleFormView description] rangeOfString:@"UIImageView"].location != NSNotFound) {
// we need to add the QuartzCore framework for the next line
[[subviewWhichIsPossibleFormView layer] setOpacity: 0.0];
}
}
}
}
}
Upvotes: 5
Reputation: 1967
It looks like there is a very simple way, but I'm pretty sure it will not pass the App Store review. Maybe someone has a clever idea? ;)
@interface UIWebBrowserView : UIView
@end
@interface UIWebBrowserView (UIWebBrowserView_Additions)
@end
@implementation UIWebBrowserView (UIWebBrowserView_Additions)
- (id)inputAccessoryView {
return nil;
}
@end
Upvotes: 4
Reputation: 2500
check out this one. https://gist.github.com/2048571. It works in iOS 5 and later, doesnt work for earlier versions.
Upvotes: 1
Reputation: 101
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
[self performSelector:@selector(removeBar) withObject:nil afterDelay:0];
}
- (void)removeBar {
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual:[UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
for (UIView *possibleFormView in [keyboardWindow subviews]) {
// iOS 5 sticks the UIWebFormView inside a UIPeripheralHostView.
if ([[possibleFormView description] rangeOfString:@"UIPeripheralHostView"].location != NSNotFound) {
for (UIView *subviewWhichIsPossibleFormView in [possibleFormView subviews]) {
if ([[subviewWhichIsPossibleFormView description] rangeOfString:@"UIWebFormAccessory"].location != NSNotFound) {
[subviewWhichIsPossibleFormView removeFromSuperview];
}
}
}
}
}
This works well.
url: http://ios-blog.co.uk/iphone-development-tutorials/rich-text-editor-inserting-images-part-6/
Upvotes: 10
Reputation: 369
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
-(void)keyboardWasShown:(NSNotification*)aNotification
{
UIWindow* tempWindow;
//Because we cant get access to the UIKeyboard throught the SDK we will just use UIView.
//UIKeyboard is a subclass of UIView anyways
UIView* keyboard;
//Check each window in our application
for(int c = 0; c < [[[UIApplication sharedApplication] windows] count]; c ++)
{
//Get a reference of the current window
tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:c];
//Get a reference of the current view
for(int i = 0; i < [tempWindow.subviews count]; i++)
{
keyboard = [tempWindow.subviews objectAtIndex:i];
if([[keyboard description] hasPrefix:@"<UIPeripheralHostView"] == YES)
{
keyboard.hidden = YES;
UIView* keyboardLayer;
for(int n = 0; n < [keyboard.subviews count]; n++)
{
keyboardLayer = [keyboard.subviews objectAtIndex:n];
NSLog(@" keyboardLayer ::: %@ " ,keyboardLayer);
if([[keyboardLayer description] hasPrefix:@"<UIWebFormAccessory"] == YES)
{
[keyboardLayer removeFromSuperview ];
}
}
keyboard.hidden = NO;
}
}
}
NSLog(@"keyboardWasShown" );
}
check this as well: http://pastebin.com/s3Fkxvsk
Upvotes: 0
Reputation: 187014
I was thinking of intercepting the UIKeyboardWillAppear notification, and giving it to a hidden text field instead, and forwarding the events through javascript to the real one in the webview. But it seems hairy. Things cursor movement and selection would then suck.
Upvotes: 1
Reputation: 1680
Not easily. You could try to go poking around the subviews in the web view but it would be taboo with Apple.
How about not putting the text field in the web page on the web side, and adding your textfield/textview to the webview explicitly so it doesn't show the nav bar at all, and you can add your own from scratch?
Upvotes: 0