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;
}
Related
In the Comcast Xfinity iPad app, there is a small button called "Filter by" at the bottom of the screen.
When a user touch the button, a overlay menu will slide up (like the menu UI in Android).
Can anyone give me some hints about how to create this kind of overlay menu?
Thanks.
For this you can create a UIView in your nib and make it look like the menu you need, then in viewdidload you can set its origin to be just off the screen and when you want it to appear just use an animation to slide it up into view and then slide it back off the screen when you're done.
In viewDidLoad:
CGRect frame = [your_menu_view].frame;
frame.origin.y += frame.size.height;
[your_menu_view].frame = frame;
When you are ready to show it:
NSTimeInterval animationDuration = 0.3;//play around with the animation length here
CGRect frame = [your_menu_view].frame;
[UIView beginAnimations:#"MenuSlideIn" context:nil];
[UIView setAnimationDuration:animationDuration];
frame.origin -= frame.size.height;
[your_menu_view].frame = frame;
[UIView commitAnimations];
Then use the same to get rid of it except subtract add its height.
haven't tested it but it should work.
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.
I have a UIScrollView inside which I have a UITextField and a UITextView.
I want to prevent the keyboard to hide the field we are working on.
If my user tap on the TextField, I want it to scroll to top of the screen.
If my user tap on the TextView, I want it to resize to the empty place left on the top of the keyboard.
My keyboard has an accessory view (a toolbar).
For now, I catch the UIKeyboardWillShowNotification notification, and I use this code, that does not really work (the textview is resized, but is still behind the keyboard) :
This code worked well when I hadn't the UIScrollView.
- (void)keyboardWillShow:(NSNotification *)notification {
if ([self.noteView isFirstResponder] == NO) return;
/*
Reduce the size of the text view so that it's not obscured by the keyboard.
Animate the resize so that it's in sync with the appearance of the keyboard.
*/
NSDictionary *userInfo = [notification userInfo];
NSValue* aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]; // Get the origin of the keyboard when it's displayed.
NSValue *animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey]; // Get the duration of the animation.
// Get the top of the keyboard as the y coordinate of its origin in self's view's coordinate system. The bottom of the text view's frame should align with the top of the keyboard's final position.
CGRect keyboardRect = [aValue CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
CGFloat keyboardTop = keyboardRect.origin.y;
CGRect newTextViewFrame = self.view.bounds;
newTextViewFrame.size.height = keyboardTop - self.view.frame.origin.y; // Using bounds here does not help
NSTimeInterval animationDuration;
[animationDurationValue getValue:&animationDuration];
// Animate the resize of the text view's frame in sync with the keyboard's appearance.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:animationDuration];
self.noteView.frame = newTextViewFrame;
[UIView commitAnimations];
}
So could you help me to :
make this work for the textview ?
make the Textview go back to its original position ?
How may I do to scroll the TextField without any resizing feature ?
Thank you
Could you just programmatically scroll the uiscrollview using this:
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated
Not sure if this will work for your application or not.
In my app I move the table view (in order to make the text fields visible when the keyboard appears). The view is looks following:
alt text http://img34.imageshack.us/img34/5845/view2.png
This is the code I use for resizing the view and moving it up:
static const NSUInteger navBarHeight = 44;
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
tableView.frame = CGRectMake(0, navBarHeight, appFrame.size.width, appFrame.size.height-navBarHeight-216); //216 for the keyboard
NSIndexPath *indPath = [self getIndexPathForTextField:textField]; //get the field the view should scroll to
[tableView scrollToRowAtIndexPath:indPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
The problem is that when the view is moved up it also moves 3 pixels into right direction (it is hard to see the difference in the screenshot, but it is visible when the animation is on and I measured the difference with PixelStick tool). Here it is how it looks after the move:
alt text http://img179.imageshack.us/img179/3310/iphonesimulator.png
My analysis shows that scrolling the table does not influence the move to the right.
Any ideas what is wrong in the code above that makes the view move to the right?
perhaps try changing this line :
tableView.frame = CGRectMake(0, navBarHeight, appFrame.size.width, appFrame.size.height-navBarHeight-216); //216 for the keyboard
to
tableView.frame = CGRectMake(tableView.frame.origin.x, navBarHeight, appFrame.size.width, appFrame.size.height-navBarHeight-216); //216 for the keyboard
just in case the origin.x of the tableview isn't at 0?
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.