iPhone - Keyboard hides TextField - iphone

I am using UITextField to receive user inputs. However, since my textfields are towards the middle/bottom of the nib, it gets hidden when the keyboard pops up. Is there any way sort of slide it along with the keyboard so that it's on the top of the keyboard during selection? Also, since I am also using the numberpad, is there an easy way to include a done button somewhere?
Thanks for the help.

I have made a simple Application for this problem. It automatically checked the Textfield's position and if keyboard hides it , it will automatically move up as per need.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField:textField up:YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField:textField up:NO];
}
- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
int animatedDistance;
int moveUpValue = textField.frame.origin.y+ textField.frame.size.height;
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait ||
orientation == UIInterfaceOrientationPortraitUpsideDown)
{
animatedDistance = 216-(460-moveUpValue-5);
}
else
{
animatedDistance = 162-(320-moveUpValue-5);
}
if(animatedDistance>0)
{
const int movementDistance = animatedDistance;
const float movementDuration = 0.3f;
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: nil context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}

To scroll when the keyboard appears, I like this tutorial from Cocoa With Love.
To dismiss the number keypad, you can put a custom "Done" button on the keypad or make an invisible button over the rest of the screen. I have done the latter with code, but this tutorial uses Interface Builder.

You'll have to do this one manually. Check out this answer.
UITextField: move view when keyboard appears

Below code works perfect for me .
[textFieldFocused becomeFirstResponder];
[self.view addSubview:startView];
[textFieldFocused resignFirstResponder];

Use this code:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification
object:self.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:self.view.window];
}
- (void)viewDidDisappear:(BOOL)animated {
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardDidHideNotification
object:nil];
}
- (void)keyboardDidHide:(NSNotification *)n
{
CGRect viewFrame = scrollView.frame;
UIDeviceOrientation orientSide = [[UIDevice currentDevice] orientation];
if ((orientSide == UIDeviceOrientationLandscapeRight) || (orientSide == UIDeviceOrientationLandscapeLeft))
viewFrame.size.height += 140;
else viewFrame.size.height += 216; //portrait mode
scrollView.frame = viewFrame;
keyboardVisible = NO;
}
- (void)keyboardDidShow:(NSNotification *)n
{
CGRect viewFrame = scrollView.frame;
UIDeviceOrientation orientSide = [[UIDevice currentDevice] orientation];
if ((orientSide == UIDeviceOrientationLandscapeRight) || (orientSide == UIDeviceOrientationLandscapeLeft))
viewFrame.size.height -= 140;
else viewFrame.size.height -= 216; //portrait mode
scrollView.frame = viewFrame;
keyboardVisible = YES; }
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
CGRect viewFrame = scrollView.frame;
if ((interfaceOrientation == UIDeviceOrientationLandscapeRight) || (interfaceOrientation == UIDeviceOrientationLandscapeLeft)) //wants to change to landscape mode
if (keyboardVisible == NO)//currently in portrait,check if keyboard was present
viewFrame.size = CGSizeMake(480,250);
else viewFrame.size = CGSizeMake(480,170);
else {//wants to change to portrait mode
if (keyboardVisible == NO)//currently in landscape,check if keyboard was present
viewFrame.size = CGSizeMake(320,416);
else viewFrame.size = CGSizeMake(320,200);
}
scrollView.frame = viewFrame;
return YES;
}
Works for landscape mode too, but only for iphone. For iPad, change the frame settings accordingly. The textFieldShouldReturn: method will make the keyboard hide when return is pressed. Hope this helps...

if someone needs it, i`ve translated the solution of ValayPatel to swift
func animatedTextField(textField: UITextField, up: Bool){
var animatedDistance : Int = 0
let moveUpValue : Int = Int(textField.frame.origin.y) + Int(textField.frame.size.height)
switch UIDevice.currentDevice().orientation {
case .Portrait , .PortraitUpsideDown:
animatedDistance = 216 - (460 - moveUpValue - 5)
default:
animatedDistance = 162 - (320 - moveUpValue - 5)
}
if (animatedDistance > 0 ){
let movementDistance : Int = animatedDistance
let movementDuration : Float = 0.3
let movement = up ? -movementDistance : movementDistance
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationBeginsFromCurrentState(true)
UIView.setAnimationDuration(NSTimeInterval(movementDuration))
self.view.frame = CGRectOffset(self.view.frame, 0, CGFloat(movement))
UIView.commitAnimations()
}
}

This situation kind of sucks on the iPhone. What you are supposed to do is either design your interface in such a way that the fields are visible when the keyboard appears, or shift the field up when the keyboard appears. (And back down when you are done)
I suggest to look at some Apple apps like Contacts or Settings to see how they are dealing with this.
Also, I'm sure the iPhone HIG has something to say about it.

I know I'm a little late in answering this but, I found a very simple solution. If you use a UITableView controller rather than a UIViewController having a tableView as an object in it, this issue does not appear.
When you click the textfield that is at the bottom of the table, the keyboard pops up and the table view automatically scrolls up till the textfield that is being edited is visible.
However the auto scrolling does not work when we use the return button on the keyboard. In this scenario we have manually scroll the table up to see the textfield.
I hope this helps

I have been searching through countless answers to similar questions. For basic single screen apps, this solutions works like a charm and is incredibly simple to implement: https://github.com/michaeltyson/TPKeyboardAvoiding
Certainly there are more elegant solutions, but this will get the job done and quick.

It's simple as setting UITableView to edition mode !
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView setEditing:YES];
}
If you would like to hide a delete bubbels, to the left of a cell then implement a UITableViewDelegate Method:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(#"%f",textField.frame.origin.y);
CGPoint scrollPoint = CGPointMake(0, textField.frame.origin);
[scrollView setContentOffset:scrollPoint animated:YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[scrollView setContentOffset:CGPointZero animated:YES];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField:textField up:YES];
}
Please use this code in your view controller.m file ..Using this code when you click the text field the keyboard will appear.Again when you click your view the keyboard will be hide ..I hope this is helps you...

Related

Turn off default rotate animation in iOS

When I rotate my iDevice form portrait to landscape, the screen rotates fine, but I'm seeing black borders moving with it, so it looks more 'real'. I find it embarrassing to see in iOS 7 and many apps have thrashed this behaviour (like Instagram).
What I want to do is hide those black borders that look totally unnecessary when rotating a device. How do I disable this standard animation?
In the parent view controller viewdidload method add this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(didRotate:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
Then add this method
- (void) didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (UIInterfaceOrientationIsLandscape(orientation) && !self.modalViewController) {
[self presentModalViewController:carouselView animated:YES];
[Globals sharedGlobals].startedAtLandscape = YES;
}
if (UIInterfaceOrientationIsPortrait(orientation) && self.modalViewController) {
[self dismissModalViewControllerAnimated:YES];
[Globals sharedGlobals].startedAtLandscape = NO;
}
}
Then to prevent animation:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if(UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
return NO;
}
return YES;
}
I found the best solution is turn animation off before rotation, and turn it back after rotation.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
...
[UIView setAnimationsEnabled:NO];
}
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
...
[UIView setAnimationsEnabled:YES];
}

UISearchBar Keyboard Return Key

I am using a UISearchBar to match text input against entries in a database and display the matched results to the user in a UITableView, as they type.
All is well, however, I cannot find a way to alter the return key type of the search bar's keyboard. By default it replaces the standard return key with a Search button. Because I am doing a live search as the user types, I do not need this button and having it there and inactive has raised some usability issues.
Attempted solutions
I can set a keyboard with the setKeyboard:UIKeyboardType method, however this doesn't seem to override the default setting of replacing the return key (on the standard keyboard) with a Search key and it does not allow access to change this return key.
I have thought about using a UITextField, giving me access to the returnKeyType property through the UITextInputTraits protocol. My problem with this however is that I am implementing the UISearchBarDelegate method searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText, which I would lose with the UITextField.
Is there a way that I can keep the functionality of the search bar's delegate methods, whilst having legitimate access to the keyboard's return key?
In fact, almost the exact screen I am implementing is found in Apple's Clock application
Screenshot:
So any help on a clean solution would be much appreciated. Note the return key on the bottom right instead of the default Search button'.
Slightly different in iOS 7 compared to the answer of #sudip.
for (UIView *subview in self.searchBar.subviews)
{
for (UIView *subSubview in subview.subviews)
{
if ([subSubview conformsToProtocol:#protocol(UITextInputTraits)])
{
UITextField *textField = (UITextField *)subSubview;
[textField setKeyboardAppearance: UIKeyboardAppearanceAlert];
textField.returnKeyType = UIReturnKeyDone;
break;
}
}
}
I tried all of these solutions without luck until I realized that in IOS8, you can just set searchBar.returnKey = .Done or whatever UIReturnKeyType you like. Sigh.
Try this:
for(UIView *subView in searchBar.subviews) {
if([subView conformsToProtocol:#protocol(UITextInputTraits)]) {
[(UITextField *)subView setKeyboardAppearance: UIKeyboardAppearanceAlert];
}
}
If you want to dismiss the return key (i.e., make it do nothing), set the "returnKeyType" property on the UITextField subview to "UIReturnKeyDone" along with "keyboardAppearence".
I had to add some lines to Neo's answer. Here is my code to add a "Done" button for UISearchbar :
for(UIView *subView in sb_manSearch.subviews) {
if([subView conformsToProtocol:#protocol(UITextInputTraits)]) {
UITextField *t = (UITextField *)subView;
[t setKeyboardAppearance: UIKeyboardAppearanceAlert];
t.returnKeyType = UIReturnKeyDone;
t.delegate = self;
break;
}
}
To change Search into Done text.
Use below code.
youtSearchBar.returnKeyType = .done
you can do it by :
- (void)viewDidLoad
{
// Adding observer that will tell you keyboard is appeared.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:)
name:UIKeyboardDidShowNotification object:nil];
[super viewDidLoad];
}
- (void)keyboardDidShow:(NSNotification *)note
{
keyboardTest = [self getKeyboard];
[keyboardTest setReturnKeyEnabled: YES];
}
- (id) getKeyboard // Method that returns appeared keyboard's reference
{
id keyboardView;
// locate keyboard view
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
UIView* keyboard;
for(int i=0; i<[tempWindow.subviews count]; i++)
{
keyboard = [tempWindow.subviews objectAtIndex:i];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2)
{
if([[keyboard description] hasPrefix:#"<UIPeripheralHost"] == YES)
{
keyboard = [[keyboard subviews] objectAtIndex:0];
keyboardView = keyboard ;
}
}
else
{
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES)
keyboardView = keyboard ;
}
}
return keyboardView ;
}
UPDATE : From iOS 7 onwards, the accepted answer will not work, below version will the work on iOS 7 onwards.
UIView *subViews = [[_searchBar subviews] firstObject];
for(UIView *subView in [subViews subviews]) {
if([subView conformsToProtocol:#protocol(UITextInputTraits)]) {
[(UITextField *)subView setEnablesReturnKeyAutomatically:NO];
}
}
for (UIView *subView in view.subviews) {
if ([subView isKindOfClass:[UITextField class]])
{
UITextField *txt = (UITextField *)subView;
#try {
[txt setReturnKeyType:UIReturnKeyDone];
[txt setKeyboardAppearance:UIKeyboardAppearanceAlert];
}
#catch (NSException * e) {
// ignore exception
}
}
}
I just found the simplest wait to hack this, just put a blank when beginning editing search field
-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar{
//Add a blank character to hack search button enable
searchBar.text = #" ";}

iPhone development common problems with UITextField and UITextViews

I've been using iPhone SDK from last 2 months.
One thing I observed is SDK isn't very nice in terms of getting text inputs.
Everytime I use a UITextView and UITextField followings are the common problems I always have to deal with:
Keyboard overlaps the textinput.
There is not a default way to hide the keyboard.
Although I know how to deal with both, for the first, I scrolls up the entire view at the keyboardshown notification call and to hide I know resignFirstResponder.
Here is how I deal with this.
But I hate the way I work!!
I don't want to copy the same code at all the .h and .m files.
I love the way the safari keyboard works like toolbar.
Kindly advice me if there is any reusable class I can use in my projects to tackle the problem.
I am sure there should be some re-usable solution to this problem as this is the common problem every developer must have seen!
UITableViewController will automatically resize its UITableView when keyboard is shown/hidden. If your UI has table-like design, you can place your controls inside UITableView so you won't have to implement resizing manually.
While it can be a pain, how could Apple possibly code that functionality to account for every possible use case?
Instead, you need to figure out what your common use cases are and then program accordingly. This is object-oriented programming - code reuse is encouraged! But, if you are copying and pasting between projects, you are doing it wrong.
For example, it is very common for me to do this with text inputes in UITableViews that are not part of a UITableView controller. Obviously, the keyboard becomes a problem that I need to fix.
So, do I write the necessary code to fix it every time? Nope, I wrote it once in a UITableView subclass and I use that class in all my projects.
Remember, good programmers are lazy and will use the tools available to them to avoid writing the same thing over and over. Create your own class, categories, etc. to handle you common problems and you'll be fine.
Textfield's and scrolling view in up/down's. using NSNotificationCenter code.
Write code in "viewDidLoad":
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector (keyboardDidShow:)
name: UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector (keyboardDidHide:)
name: UIKeyboardDidHideNotification object:nil];
add to code in delegate methods:
-(void) keyboardDidShow: (NSNotification *)notif
{ [calendarView removeFromSuperview];
// If keyboard is visible, return
if (keyboardVisible)
{
NSLog(#"Keyboard is already visible. Ignore notification.");
return;
}
// Keyboard is now visible
keyboardVisible = YES;
}
-(void) keyboardDidHide: (NSNotification *)notif
{ [calendarView removeFromSuperview];
// Is the keyboard already shown
if (!keyboardVisible)
{
NSLog(#"Keyboard is already hidden. Ignore notification.");
return;
}
if (up == 1) {
up = 0;
[self down];
}
// Keyboard is no longer visible
keyboardVisible = NO;
}
add to remaining default methods:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if(textField == txt_Zip){
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
return !([newString length] > 6);
}
else {
return YES;
}
}
-(void) touchesBegan :(NSSet *) touches withEvent:(UIEvent *)event
{
if(up==1)
{
up=0;
[self down];
}
[txtMake_Model resignFirstResponder];
[txtSerial_Vin resignFirstResponder];
[txtDaysPerWeek resignFirstResponder];
[txtAnnualMiles resignFirstResponder];
[txtPurchasedDate resignFirstResponder];
[txtInterestLocation resignFirstResponder];
[txtInterestSequence resignFirstResponder];
[txtInterestName resignFirstResponder];
[txt_City resignFirstResponder];
[txtAddress1 resignFirstResponder];
[txtAddress2 resignFirstResponder];
[txt_Zip resignFirstResponder];
[txtAdditionalInfo resignFirstResponder];
[txtVehicleNumber resignFirstResponder];
[txtMilesToWork resignFirstResponder];
[txtCostNew resignFirstResponder];
[super touchesBegan:touches withEvent:event ];
}
//- (BOOL)textFieldShouldReturn:(UITextField *)textField // called when 'return' key pressed. return NO to ignore.
//{
// [textField resignFirstResponder];
// return YES;
//}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
if (up==1) {
up =0;
[self down];
}
return YES ;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField{
if(textField == txtInterestSequence)
{ if(up==0){up=1;[self moveUp];}
}else if(textField == txtInterestName)
{ if(up==0){up=1;[self moveUp];}
}else if(textField == txtAddress1)
{ if(up==0){up=1;[self moveUp];}
} else if(textField == txtAddress2)
{ if(up==0){up=1;[self moveUp];}
} else if(textField == txt_City)
{ if(up==0){up=1;[self moveUp];}
} else if(textField == txt_Zip)
{ if(up==0){up=1;[self moveUp];}
} else if(textField == txtAdditionalInfo)
{ if(up==0){up=1;[self moveUp];}
} else if(textField == txtMilesToWork)
{ if(up==0){up=1;[self moveUp];}
} else if(textField == txtCostNew)
{ if(up==0){up=1;[self moveUp];}
}
}
-(void)moveUp{
// up=1;
[UIView beginAnimations:nil context:nil];
self.view.center=CGPointMake(self.view.center.x, self.view.center.y-200);
[UIView commitAnimations];
}
-(void)down{
[UIView beginAnimations:nil context:nil];
self.view.center=CGPointMake(self.view.center.x, self.view.center.y+200);
[UIView commitAnimations];
// up=0;
}

Question about passing a NSNotification for scrolling a view when keyboard shows

I have a view with five UITextFields spaced from top to bottom. When you click in a text field the keyboard pops up and covers the bottom two text fields. I have tweaked the code to the point where if you click in one of the bottom two text fields the view will scroll up so that text field is visible.
The problem I am having is when you start in the first text field and tab through the text fields the view does not scroll when you get to the last two text field. I have determined this is because when tabbing between views my method keyboardWillShow never gets called again after we have clicked in the first text Field.
I have tried using the textFieldDidBeginEditing method to determine which text field now has focus and then I wanted to call my keyboardWillShow method again. But that method takes a NSNotification as an argument and through all of my search I have seen that you never really want to create an NSNotification object and instead want to use postNotificationName from NSNotificationCenter to pass a NSNotification object. I have been unable to get this to work properly.
Here's the relevant code I have.
- (void) viewWillAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.window];
[super viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[super viewWillDisappear:animated];
}
- (void) keyboardWillShow: (NSNotification *)notif
{
// get our app delegate so we can access currentTextField
ScrollingAppDelegate *appDelegate = (ScrollingAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.notif = notif;
NSDictionary *info = [notif userInfo];
NSValue *aValue = [info objectForKey: UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
float bottomPoint = (appDelegate.currentTextField.frame.origin.y+ appDelegate.currentTextField.frame.size.height+10);
scrollAmount = keyboardSize.height - (self.view.frame.size.height - bottomPoint);
if (scrollAmount > 0)
{
moveViewUp = YES;
[self scrollTheView:YES];
}
else
{
moveViewUp = NO;
}
}
- (void)scrollTheView: (BOOL)movedUp
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGRect rect = self.view.frame;
if (movedUp)
{
rect.origin.y -= scrollAmount;
}
else
{
rect.origin.y += scrollAmount;
}
self.view.frame = rect;
[UIView commitAnimations];
}
- (void) textFieldDidBeginEditing:(UITextField *)textField
{
// declare app delegate so we can access a varibale in it.
ScrollingAppDelegate *appDelegate = (ScrollingAppDelegate *)[[UIApplication sharedApplication] delegate];
// set the app delegate variable currentTextField to the textField which just got focus so we can access it
// in our other method keyboardWillShow
appDelegate.currentTextField = textField;
// some how call keyboardWillShow here so the view will scroll to the current text field
}
If I am going about this all wrong please let me know. I have been searching the net for answers but the have eluded me so far. Everything I find about scrolling the view only handles one text field and not multiple the way I need it.
Thanks
I didn't bookmark the original post I found this in, but here's a link to the code snipet I've been using for exactly this kind of thing:
https://gist.github.com/295089

UIWebView Keyboard - Getting rid of the "Previous/Next/Done" bar

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
- (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/
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];
}
}
}
}
}
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
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.
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.
check out this one. https://gist.github.com/2048571.
It works in iOS 5 and later, doesnt work for earlier versions.
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];
}
}
}
}
}
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?
[[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