Get event for external/virtual keyboard while textField become first responder - iphone

In my iPad application, i am presenting a controller using form sheet style as
controller.modalPresentationStyle=UIModalPresentationFormSheet;
In landscape mode while device's keyboard open i m setting size of tableView so that user can able to see all records of table.
To get event of show/hide keyboard. I have set NSNotification
Problem
But when user tap in textField of table cell using external/virtual keyboard, i m not getting event of keyboard show/hide.
So when textfield becomes first responder, Tableview size is decreasing but it's no need while user connected with external keyboard.
Can anyone please guide/help here, what can i do? So that i can stop do set size when using external keyboard.
Register Keyboard Event
- (void)registerForKeyboardNotifications{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification object:nil];
}
Set Frame While AutoRotate and Text Field Become First Responder
-(void)setFramesOfTable
{
CGRect rct=tableView.frame;
if(appDel.isThisIPad && ([[UIApplication sharedApplication] statusBarOrientation]==UIInterfaceOrientationLandscapeLeft || [[UIApplication sharedApplication] statusBarOrientation]==UIInterfaceOrientationLandscapeRight) && [selectedField isFirstResponder])
{
rct.size.height=400.0;
}
else
{
rct.size.height=576.0;
}
tableView.frame=rct;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField{
selectedField = textField;
[self setFramesOfTable];
}
-(NSUInteger)supportedInterfaceOrientations
{
[self setFramesOfTable];
return UIInterfaceOrientationMaskAll;
}
Thanks.

Its not a good idea to change the frame of the table when the text field begins editing. On the iPad, the user can have an external keyboard, the docked keyboard or the split keyboard.
If the user has an external keyboard, you don't need to resize your window. The onscreen keyboard does not appear when using an external keyboard so there is no reason to resize windows.
If the user is using the split keyboard, you don't really need to worry about resizing windows. if they split the keyboard, they could put the keyboard in the middle of the UI, making it impossible (or at very least impractical) to rearrange your UI so its not covered by at least a small portion of the split keyboard. If the user splits the keyboard and covers up important UI components, they need to move the keyboard out of the way.
The best way to resize your UI is in the keyboard will ChangeFrame/Hide methods
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
inside your handlers of these events, you can get the keyboard height, and adjust the UI accordingly
-(void)keyboardWillChangeFrame:(NSNotification*)notification
{
NSDictionary* info = [notification userInfo];
NSValue* kbFrame = info[UIKeyboardFrameEndUserInfoKey];
NSTimeInterval animationDuration = [info[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect keyboardFrame = [kbFrame CGRectValue];
BOOL isPortrait = UIDeviceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation);
CGFloat height = isPortrait ? keyboardFrame.size.height : keyboardFrame.size.width;
}
this gets you the animationDuration and the height of the keyboard so that you can use a UIView animateWithDuration block to animate the frame change to your tableview so that it is not obscured by the keyboard.
in keyboardWillHide: you only need to get the animationDuration (the same way as above) from the NSNotification (the height will obviously be 0). Then use another UIView animateWithDuration block to animate your tableview resizing back to its original size

Related

Adjust static UITableView when keyboard appears?

I am working on a app which contains UITextField and UITextView in static UITableView. I am facing two issues
When I select UITextField it moved correctly but it is not working for UITextView.
When the keyboard disappears the UITableView not shown properly.
All I want is to adjust UITextField and UITextView accordingly when keyboard appears and disappears. Here is my code.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
- (void)keyboardWillShow:(NSNotification *)notification {
//get the end position keyboard frame
NSDictionary *keyInfo = [notification userInfo];
CGRect keyboardFrame = [[keyInfo objectForKey:#"UIKeyboardFrameEndUserInfoKey"] CGRectValue];
//convert it to the same view coords as the tableView it might be occluding
keyboardFrame = [self.tableView convertRect:keyboardFrame fromView:nil];
//calculate if the rects intersect
CGRect intersect = CGRectIntersection(keyboardFrame, self.tableView.bounds);
if (!CGRectIsNull(intersect)) {
//yes they do - adjust the insets on tableview to handle it
//first get the duration of the keyboard appearance animation
NSTimeInterval duration = [[keyInfo objectForKey:#"UIKeyboardAnimationDurationUserInfoKey"] doubleValue];
//change the table insets to match - animated to the same duration of the keyboard appearance
[UIView animateWithDuration:duration animations:^{
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, intersect.size.height, 0);
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, intersect.size.height, 0);
}];
}
}
- (void) keyboardWillHide: (NSNotification *) notification{
NSDictionary *keyInfo = [notification userInfo];
NSTimeInterval duration = [[keyInfo objectForKey:#"UIKeyboardAnimationDurationUserInfoKey"] doubleValue];
//clear the table insets - animated to the same duration of the keyboard disappearance
[UIView animateWithDuration:duration animations:^{
self.tableView.contentInset = UIEdgeInsetsZero;
self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero;
}];
}
Try with the UITableView's instance method: scrollToRowAtIndexPath:atScrollPosition:animated:
In keyBoardWillShow use the tableview's or the textfield's index path and set the scroll position to UITableViewScrollPositionTop.
If it doesn't work as you want it to, try with scrollToRowAtIndexPath:atScrollPosition:animated:
Hope this helps, good luck! :))
For further information, check out Apple's UITableView reference: https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html
You can use a third party library for avoiding keyboard scrolling above of text field or text views.
Use https://github.com/cokecoffe/ios-demo/blob/master/TPKeyboardAvoiding/TPKeyboardAvoidingScrollView.m
OR
You can use UITableviewController as your view controller class.Change the Tableview content property to Static. Then you can add any UI controls to the static cells of the table view from story board.
If you select any text field or text view in your tableview, then key board automatically shows below of your text field or text view without any programming logic.

How to detect only when keyboard is being shown?

I wanted my UIView to animate to a new position when the keyboard was shown, so used the UIKeyboardWillShowNotification and UIKeyboardWillChangeFrameNotification. The problem is that when the device is rotated without the keyboard, the view has autoresizing and rotates as it should - it looks perfect.
Unfortunately, with the keyboard displayed, rotating the device sends those notifications and thus performing a UIView animation in response gives it an odd animation. It could best be described as looking like it jumps into a new position and is then anchored round by a corner to the new orientation. Perhaps you know what I'm talking about.
Is there any way for me to detect when the device is rotating or otherwise deal with the problem when rotating when the keyboard is being shown?
For orientation-change detection use the UIDeviceOrientationDidChangeNotification.
I guess the following code will help you..
#property(nonatomic,strong)BOOL keyBoardShow;
- (void)viewDidLoad
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeShown:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
[super viewDidLoad];
}
-(void)keyboardWillBeShown:(NSNotification *)aNotification {
keyBoardShow = YES;
}
-(void)keyboardWillBeHidden:(NSNotification *)aNotification {
keyBoardShow = NO;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (keyBoardShow) {
// Do the needful when the keyboard is shown
}else{
}
}
Just set bool value in keyboardWillBeShown and keyboardWillBeHidden delegate methods. And do your uiview position in willRotateToInterfaceOrientation.
Instead of relying on the built-in notifications, why don't you instead rely on what's triggering the keyboard showing in the first place? I'm guessing the keyboard pops up when a particular UITextField becomes the first responder. You should be able to use that.
Register a delegate for that UITextField and implement -textFieldDidBeginEditing:. The delegate should be a view controller. Then, to keep things loosely coupled, post your own notification from the delegate and have your view registered for that.
It's a bit more work, but it gives you much better control.
- (void)textFieldDidBeginEditing:(UITextField *)textField
Apple documentation: UITextFieldDelegate Protocol

Webview doesn't return his place after typing in input field

I'm working on some iPhone application that contain a webview with these properties:
[[webView.subviews objectAtIndex:0] setScrollEnabled:NO]; //to stop scrolling
[[webView.subviews objectAtIndex:0] setBounces:NO]; //to stop bouncing
On the webview there is a text input
The problem is that after I'm trying to type an input, the keyboard is rising and all the page too. but after the keyboard is down the page itself stay upwards.
1
Because the webview is without scrolling it can't be possible to see the page correctly until I restart the app.
any ideas?
Here is a simple solution. First add this line of code in your - (void)viewDidLoad of your view controller:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardDidHide:)
name:UIKeyboardDidHideNotification
object:nil];
This is so you get notified when the keyboard hides.
Add the following method to your view controller:
- (void)keyboardDidHide: (NSNotification*) notification
{
UIScrollView* scroll = nil;
if([webView respondsToSelector: #selector(scrollView)])
scroll = webView.scrollView; //iOS5 and up
else
scroll = [webView.subviews objectAtIndex:0]; //iOS4 and below
[scroll setContentOffset: CGPointMake(0, 0)];
}
This will cause your UIWebView to scroll to 0, 0 (top) whenever the keyboard is hidden.

UIScrollView not working properly

I have one view window which I created in the interface builder. I created a UIScrollView which fills the entire window and dragged some other items into it, including a UITextView. The problem I encountered was that when I click to write into the TextView the keyboard blocks the view of the TextView, hence the use of a ScrollView.
Now I've searched around quite a bit and think I know what I need to do but if I'm doing it right is another matter.
I get the bounce, that is I can drag everything that's in the ScrollView and it will bounce back. When I then press to write in the TextView the keyboard pops up, this shrinks the ScrollView to "screen size" - "keyboard size" (I know this happens as I haven't implemented the "do this once I hide the keyboard" function yet, so when I hide the keyboard the ScrollView now ends where the keyboard started). But even though the view size is now smaller than the content size it does not scroll, simply continues to bounce.
Here below you can see the code I'm using. I call the registerForKeyboardNotifications in viewDidLoad.
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification *)n
{
NSLog(#"WoopWoopWoop");
NSDictionary* userInfo = [n userInfo];
// get the size of the keyboard
CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
// resize the noteView
CGRect viewFrame = self.mainScrollView.frame;
viewFrame.size.height -= (keyboardSize.height);
mainScrollView.bounces = YES;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.4];
[self.mainScrollView setFrame:viewFrame];
[UIView commitAnimations];
}
I've tried setting the content view to some arbitrary size such as
[mainScrollView setContentSize:CGSizeMake(3200.0,2300.0)];
but that has had no effect...
Any ideas?
Hi, you don't need to make use of notifications. Just make use of the UITextFieldDelegate protocol methods. You can set the content Offset for the scrollView in those methods.
For example:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
//Check the necessary textfield and then change yValue accordingly
[scrollView setContentOffset:CGPointMake(0,yValue) animated:YES];
return YES;
}
when I click to write into the TextView the keyboard blocks the view of the TextView, hence the use of a ScrollView.
First, I would suggest that this use of UIScrollViews is not necessary (if you only have a UITextView to display. Also, remember that UITextView is a subclass of UIScrollView).
You can achieve repositioning and resizing of your UITextView by configuring it as a subview of a UIView instead. Enable autoresizesSubviews on your UIView and configure both views' springs and struts via the IB Inspector. The UIView container should take all the available space.
Using the same approach as described in your question, when the UIView is resized, it should automatically adjust the UITextView's frame as well.
Now, even if you do need to have a view hierarchy with a UIScrollView at the top, I would still suggest to wrap that into a plain UIView container, and configure autoresizing as I mentioned above.
Hope that helps!

Problem with scrollview, it scrolls more

I have a scrollView and i want to scroll it automatically when i select an textField
(i am filling a form here)
i am using following method to scroll it
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[scrollView setContentOffset:CGPointMake(0,50*(textField.tag-1))];
}
Now the problem is that i have more than 10 text fields and when i reached to the seventh textField the scrollView scrolls more .
I also tried to print the CGPointMake()'s values...and it is showing correct values..but the scroller goes beyond the range what is expected..
Look at following images
The following 2 images showing control on textFields tag <7
But when control reaches to 7th textField it scrolls more
and after this it goes beyond bounds.
This problem occurs only when i move from one textFields to another without pressing that return button(i mean with resignFirstResponder).But when i press that return button and then go to the next field then all works fine.
Can anyone suggest where should be the problem..?
It won't scroll because it doesn't contain enough content. It will stop when the bottom edge of the content reaches the bottom end of the frame. Use something like
CGSize size = scrollView.contentSize;
scrollView.contentSize = CGSizeMake (size.width, size.height + ADDITIONAL_HEIGHT);
when setting up the scroll view, or in your -viewDidLoad: method, if it was loaded from a XIB.
It should keep the text field being edited on the screen - i.e. scroll automatically - so you shouldn't need to do anything?
However, it might be trying to edit a text field that is behind the keyboard - so the better solution would be:
//Get notifications of the keyboard opening and closing
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
- (void)keyboardWillShow:(NSNotification *)notification {
//Get the keyboard height
int h = [self.view convertRect:[[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] toView:nil].size.height;
//Change the inset of the scroll view and scroll bars
scrollView.contentInset = scrollView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, h, 0);
}
- (void)keyboardWillHide:(NSNotification *)notification {
scrollView.contentInset = scrollView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, 0, 0);
}
try this.declare a variable
CGPoint svos;
in .h file and do this.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
svos = scr.contentOffset;//scr is my scroll view
CGPoint pt;
CGRect rc = [textField bounds];
rc = [textField convertRect:rc toView:scr];
pt = rc.origin;
pt.x = 0;
pt.y -= 60;
[scr setContentOffset:pt animated:YES];
//NSLog(#"%f",pt.y);
}