How can I make the keyboard disappear? - iphone

Is there a way to make a keyboard disappear without resignFirstResponder? I have a UITextField, and I'd like it to be able to accept new text and still have the insertion point (flashing cursor) visible without the keyboard being on screen.
When I perform a [textField resignFirstResponder] I can still insert text, by appending to the textField.text, but I can't see the insertion point anymore.
Is there a standard way to make the keyboard animate out, while having my textField remain first responder?
Thanks.

Found an answer to this question. It's not standard though, and like Dave says, may be taboo for the app reviewers. Using the code from this page as a starting point:
http://unsolicitedfeedback.com/2009/02/06/how-to-customize-uikeyboard-by-adding-subviews/
I added in an animation block. You can dismiss the keyboards view with a standard looking animation, but whatever is first responder will retain that status. Really, the keyboard is just hidden off screen.
- (void)hideKeyboard
{
for (UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows]) {
// Now iterating over each subview of the available windows
for (UIView *keyboard in [keyboardWindow subviews]) {
// Check to see if the view we have referenced is UIKeyboard.
// If so then we found the keyboard view that we were looking for.
if([[keyboard description] hasPrefix:#"<UIKeyboard"] == YES) {
// animate the keyboard moving
CGContextRef context = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.4];
// remove the keyboard
CGRect frame = keyboard.frame;
// if (keyboard.frame.origin.x >= 0) {
if (keyboard.frame.origin.y < 480) {
// slide the keyboard onscreen
//frame.origin.x = (keyboard.frame.origin.x - 320);
// slide the keyboard onscreen
frame.origin.y = (keyboard.frame.origin.y + 264);
keyboard.frame = frame;
}
else {
// slide the keyboard off to the side
//frame.origin.x = (keyboard.frame.origin.x + 320);
// slide the keyboard off
frame.origin.y = (keyboard.frame.origin.y - 264);
keyboard.frame = frame;
}
[UIView commitAnimations];
}
}
}
}
I wrote in code to dismiss the keyboard to the left and to the bottom of the screen. I don't know what will happen when you eventually resignFirstResponder, but it might be an idea to reset the keyboard frame when you do that.

If there is, then it's not documented in the iPhone API. Also, what you're asking for does not make sense. You want to have the insertion point in a UITextField. OK, great. But you also want the keyboard to go away? Then what's the point of the textfield having the focus? How are you going to input data into the textfield? If you want to have a custom keyboard, then just display it on top of the keyboard. I can't think of a good reason why you'd want the cursor to be visible but not have some sort of data entry mechanism. That would break UI convention and might even get your app rejected.

Related

UIScrollView only required when keyboard is displayed

I have tried multiple implementations of a scroll view to handle a keyboard's presence, including apple's own. I can't get any of them to work.
I have a view that requires no scrolling when the keyboard is not displayed, but once a text field is the first responder, and the keyboard displays, some content needs to be scrollable.
Note that the only editable text field is the first on the screen, so I do not need to scroll the view to unhide anything - I just need scrolling ability in the top half of the screen, but only when the keyboard is displayed.
This is as close as I can get:
I can successfully register for keyboard notifications. On loading, I am setting my scrollview and content size to the full height of the view. When the keyboard displays, I resize the scrollview to the original height minus the keyboard height:
scrollView.frame = CGRectMake(0, 0, 320, 416 - kbSize.height);
And on hide, I simply reset it:
scrollView.frame = CGRectMake(0, 0, 320, 416);
This almost works. Except, once the keyboard is displayed, if I scroll down to the bottom of the view (keeping the keyboard displayed) and then hide the keyboard using its return key, when the scroll view resizes there is an inelegant 'jump' back to the top of the screen. There is no smooth animated scrolling to resize the scrollview.
Any ideas? I think I am making a hack of this compared to Apple's implementation, but it is the closest I have got.
Yeah like Justin Paulson commented, but here is the code
[UIView animateWithDuration:0.3 animations:^{
self.scrollView.frame = newFrame;
}];
I think you can just fix the scroll position before the dismiss:
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
// like this:
self.contentOffset = CGPointMake(0,0);
// you can animate the frame change here, or where you were doing it
[UIView animateWithDuration:0.2 animations:^{
scrollView.frame = CGRectMake(0, 0, 320, 416);
}];
return YES;
}

Raise View when keyboard visible in landscape

I have a problem when in landscape rotation on my App. Everything moves to where I want it etc, but when the keyboard is visible, one of the text fields is covered. I have written some code that pushes the view up to resolve this. This bit of code works fine in portrait, but in landscape, the view rotates back to portrait. The code is below:
- (void)textFieldDidBeginEditing: (UITextField *)textField {
CGAffineTransform translation = CGAffineTransformIdentity;
if (textField == self.incVATField)
translation = CGAffineTransformMakeTranslation(0, -30);
[UIView beginAnimations:nil context:nil];
self.view.transform = translation;
[UIView commitAnimations];
}
Can anyone tell me how to resolve this, so that when the device in lanscape, the view just gets pushed up a little so I can still see the text field?
Thanks
When the editing of the text field begins, just adjust the frame of the view so that u can see the text.
- (void)textFieldDidBeginEditing: (UITextField *)textField {
self.view.frame = CGRectMake(x_origin,y_origin,width,height);
}
Another option:
You can also do this by making your view a sub view of scroll view and changing the content offset to the required point so that the text field is visible.

keyboard hiding textfields in tableViewController

I am using a tableViewController having 2 sections ....
1st section has 7 rows & 2nd section has 2 rows.
So when i edit in textfields of 2nd section keyboard hides these field so how i will handle
keyboard for these fields only.(i am using tableviewController which has default scrolling).
I am new to objective -C.....Your help please.
Thanks.
On tapping any cell with text field, you can navigate to another view with only a text field, keyboard and Done and Cancel buttons. this feels pretty neat. You can see this in many of apple's iphone apps as well... e.g. Go to iPhone Settings -> Mail, Contacts, Calendars -> Signature.
EDIT: since you cant use the standard way you can move the complete view up with following code:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
CGPoint currentCenter = [self.view center];
CGPoint newCenter = CGPointMake(currentCenter.x, currentCenter.y - 150);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
[self.view setCenter:newCenter];
[UIView commitAnimations];
return YES;
}
change the animation duration and the change in position of the center (150) in this code according to your requirements. I have assumed that your view controller is the delegate for your textfield.
To bring the view back to it's original position, use same code but add to center.y in textFieldShouldReturn or textFieldShouldEndEditing etc
CGPoint newCenter = CGPointMake(currentCenter.x, currentCenter.y - 150);
P.S. : I'm still not sure you should be using this second approach.

UIPopoverController animates when keyboard pops up

Heey,
In my iPad application I have a UIPopoverController with a UIViewController containing some textfields.
When the keyboard comes up, the Popover gets animated to fit. Does anybody know how to disable this?
Thanks
I dont think you can except make the popovers smaller in height...Its done like that so when your keyboard pops up none of the popover gets covered by it (thus it shrinks back), however i have found it to be annoying at times since it messed with table views (not making them able to scroll all the way and having to resize them)
It would be great if it did actually animate to better part of the screen, I think you mean it actually shrinks the popUp which is mostly not good.(which i see during rotation in my case). You can not keep the popUp from squishing, UNLESS you move a view. The best way to handle this is to temporarily move your entire main UIView of the whole screen up with the keyBoard by the difference between the size of your pop up, and how much that pop up would shrink if you did not move it up... you can't just move it up by the size of your keyboard, because popUps up high would then also be effected. This code below is for when the keyboard rotated, similar code for when it is first introduced. easy to do, EXCept for when you rotate the screen, then things get tricky...
in otherwords, sometimes your UIView will not move at all, sometimes it will move up by a good 170 points.
//-----------------finding the keyboard top (also used on "didRotate")----very handy,
// took me hours to figure out an absolute always work topOfKeyboard, so here you go.-------
//--------------------------------------------------------------------------------
- (void)keyboardWillShow:(NSNotification*)notification
{
NSLog(#" keyboardWillShow");
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
NSDictionary* info = [notification userInfo];
keyboardRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardRect = [(UIView*)keyWindow convertRect:keyboardRect toView:mainViewController.view];
keyboardIsVisible = TRUE;
topOfKeyboard = keyboardRect.origin.y;
the tricky part is finding the PopUp bottom, because there appears to be code in the popup itself or the convertRect:toView: code that makes the origin flaky , (if you try to "view" origin after a "convertRect:toView:" code), it wants to move and be in different spots during rotation,(or one of it's super views) so bottom calc comes out different some times,(not predicable) because of async process of the rotation of different elements possibly because the popUp itself has many superviews down in the pop up. (to see problem in action with pop up and, must have keyboard effecting popup, move the whole view up then log the "origin" and "size" of popUp after the "convertRect:toView:" code)... the "origin" i'm talking about is the origin of the frame after it is translated to the main view (or atleast a couple views up) with the "convertRect:toView:" code....
update:(it appears if you move down about 3 superviews from the popUp, the flakiness goes away... (this code below was in a "didRotate" ipad type of code. That is that the popUp has several superviews before you can get to the one that is projected ontop of the proper frame
UIPopoverController probably should have a property that has the origin that is predicted after a rotation in it, in a type of "will rotate" kind of code, (because of the keyboard problem), instead of just the "popoverContentSize", (also should include the popoverContentSize that would have been without the keyboard as another variable, ".. anyway This is how I had to do it, see code below.
//--------------------------------------------------------------------------------
- (void) checkRotation
{
NSLog(#" ");
NSLog(#"checkRotation");
if (wasOffset)
{
wasOffset = false;
[UIImageView beginAnimations:nil context:NULL];
[UIImageView setAnimationDuration:0.2f];
CGRect frame = carousel.frame;
frame.origin.y += offset;
carousel.frame = frame;
[UIImageView commitAnimations];
[popPickerController presentPopoverFromRect:zoneButton.frame inView:[zoneButton superview] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
if (popPickerController.popoverVisible)
{
if (keyboardIsVisible)
{
wasOffset = false;
[popPickerController presentPopoverFromRect:zoneButton.frame inView:[zoneButton superview]
permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
upView3 = [[[popPickerController.contentViewController.view superview] superview] superview]; //hey it works... :o)
//NSLog(#" ");
//NSLog(#"upView3.frame.origin.x = %f",upView3.frame.origin.x);
//NSLog(#"upView3.frame.origin.y = %f",upView3.frame.origin.y);
//NSLog(#"upView3.frame.size.height = %f",upView3.frame.size.height);
//NSLog(#"upView3.frame.size.width = %f",upView3.frame.size.width);
//NSLog(#" ");
popUpRect.origin.x = upView3.frame.origin.x;
popUpRect.origin.y = upView3.frame.origin.y;
popUpRect.size.height = popUpSize.height;
popUpRect.size.width = popUpSize.width; //you must save the size because the keyboard destroys it before you can use it. very tricky....
//NSLog(#" ");
//NSLog(#"popUpRect.origin.x = %f",popUpRect.origin.x);
//NSLog(#"popUpRect.origin.y = %f",popUpRect.origin.y);
//NSLog(#"popUpRect.size.height = %f",popUpRect.size.height);
//NSLog(#"popUpRect.size.width = %f",popUpRect.size.width);
//NSLog(#" ");
//NSLog(#" ");
//NSLog(#"keyboardIsVisible = %d", keyboardIsVisible);
//NSLog(#" ");
//NSLog(#"keyboardRect.origin.x = %f",keyboardRect.origin.x);
//NSLog(#"keyboardRect.origin.y = %f",keyboardRect.origin.y);
//NSLog(#"keyboardRect.size.height = %f",keyboardRect.size.height);
//NSLog(#"keyboardRect.size.width = %f",keyboardRect.size.width);
//NSLog(#"topOfKeyboard = %f",topOfKeyboard);
CGFloat bottomOfPicker = popUpRect.origin.y + popUpRect.size.height - amountShadowCanEncroach;
//NSLog(#" ");
//NSLog(#"bottomOfPicker = %f",bottomOfPicker);
//NSLog(#"topOfKeyboard = %f",topOfKeyboard);
//NSLog(#" ");
if (bottomOfPicker > topOfKeyboard)
{
wasOffset = true;
offset = bottomOfPicker - topOfKeyboard;
NSLog(#"offset = %f",offset);
[UIImageView beginAnimations:nil context:NULL];
[UIImageView setAnimationDuration:0.2f];
CGRect frame = carousel.frame;
frame.origin.y -= offset;
carousel.frame = frame;
[UIImageView commitAnimations];
}
}
[popPickerController presentPopoverFromRect:zoneButton.frame inView:[zoneButton superview] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
and moving the main UIView back
//-----------------------------------------------------------------------------
- (void) searchDidEndEditing
{
NSLog(#"searchDidEndEditing");
keyboardIsVisible = false;
if (wasOffset)
{
wasOffset = false;
[UIImageView beginAnimations:nil context:NULL];
[UIImageView setAnimationDuration:0.2f];
CGRect frame = mainView.frame;
frame.origin.y += offset;
mainView.frame = frame;
[UIImageView commitAnimations];
if (zoneButton.selected)
[popPickerController presentPopoverFromRect:zoneButton.frame inView:[zoneButton superview] permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}

iPhone SDK: After a certain number of characters entered, the animation just won't load

Okay, this is the code:
[lblMessage setText: txtEnter.text];
[lblMessage sizeToFit];
scrollingTextView.contentSize = lblMessage.frame.size;
float width = (lblMessage.frame.size.width) + (480);
[UIView beginAnimations:#"pan" context:nil];
[UIView setAnimationDuration:durationValue];
[UIView setAnimationRepeatCount:5];
scrollingTextView.contentOffset = CGPointMake(width,0);
[UIView commitAnimations];
//The scrolling text view is rotated.
scrollingTextView.transform = CGAffineTransformMakeRotation (3.14/2);
[self.navigationController setNavigationBarHidden:YES];
btnChange.transform = CGAffineTransformMakeRotation (3.14/2);
I have the user enter in some text, press a button and then a label is replaced with the text, turned 90 degrees in a scrollview on a page.
After a certain number of characters, for example say 20.. the animation just won't load. I can go back down until the animation will run.
Any ideas on where I am going wrong, or a better way of storing the text etc etc ?
Core Animation animations are performed on a separate thread. When you enclose the change in contentOffset in a beginAnimations / commitAnimations block, that change will be animated gradually. The scrolling text view rotation that occurs next, outside of the animation block, will be performed instantly. Since both are interacting with the same control on different threads, it's not surprising that you're getting weird behavior.
If you want to animate the rotation of the text in the same way as the contentOffset, move that line of code to within the animation block.
If you want to have the rotation occur after the offset change animation has completed, set up a callback delegate method. You can use code in the beginning of your animation block similar to the following:
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(contentOffsetAnimationHasFinished:finished:context:)];
which requires you to implement a delegate method like the following:
- (void)contentOffsetAnimationHasFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context;
{
// Do what you need to, now that the first animation has completed
}
EDIT (2/6/2009):
I just created a simplified version of your application, using only the sideways text scrolling, and find no problem with the animation on the device with any number of characters. I removed all extraneous calls to layout the buttons, etc., and only animate the text. Rather than apply the rotation transform to the scroll view every time you click the button, I have it start rotated and stay that way.
I thought it might be a layer size issue, as the iPhone has a 1024 x 1024 texture size limit (after which you need to use a CATiledLayer to back your UIView), but I was able to lay out text wider than 1024 pixels and still have this work.
A full Xcode project demonstrating this can be downloaded here. I don't know what your issue is, but it's not with the text animating code you present here.
Right, this code is working fine in the simulator, and works fine until i enter more than say 20 characters in txtEnter.text:
- (IBAction)updateMessage:(id)sender
{
//Animation coding
//Put the message in a resize the label
[lblMessage setText: txtEnter.text];
[lblMessage sizeToFit];
//Resize the scrolliew and change the width.
scrollingTextView.contentSize = lblMessage.frame.size;
float width = (lblMessage.frame.size.width) + (480);
scrollingTextView.transform = CGAffineTransformMakeRotation (3.14/2);
//Begin the animations
[UIView beginAnimations:#"pan" context:nil];
[UIView setAnimationDuration:durationValue];
[UIView setAnimationRepeatCount:5];
//Start the scrolling text view to go across the screen
scrollingTextView.contentOffset = CGPointMake(width,0);
[UIView commitAnimations];
//General hiding and showing points.
[txtEnter resignFirstResponder];
[btnChange setHidden:NO];
[txtEnter setHidden:YES];
[btnUpdate setHidden:YES];
[lblSpeed setHidden:YES];
[lblBackground setHidden:YES];
[backgroundColourControl setHidden:YES];
[speedSlider setHidden:YES];
[scrollingTextView setHidden:NO];
[backgroundImg setHidden:NO];
[toolbar setHidden:YES];
[self.navigationController setNavigationBarHidden:YES animated:YES];
//Depending on the choice from the segment control, different colours are loaded
switch([backgroundColourControl selectedSegmentIndex] + 1)
{
case 1:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:YES];
break;
case 2:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:YES];
break;
default: break;
}
btnChange.transform = CGAffineTransformMakeRotation (3.14/2);
}
I've tried your method Brad, but can't seem to get the (void) section to work properly.
What my app does its fill the label with a message and then rotates them all to act like it's in landscape mode. Then what it does it scroll the label within a scrollview to act like a scrolling message across the screen.