There's UITextView
inserted into tab in UITabBarController
(on the iPhone).
UITextView
with a lot of lines.What's happen? The keyboard hide a half of UITextView
with cursor. Can't edit the text as the result.
How to resolve the issue for all Apple mobile devices (with different screen resolution)? Thanks a lot for help!
The best result was reached by the following code. Also don't forget to set background color to UIView
and place UITextView
before other top-screen controls (e.g. UITabBar).
Editing of a text in the end still isn't perfect now. You may try to improve.
FirstViewController.h:
@interface FirstViewController : UIViewController {
IBOutlet UIBarButtonItem *buttonDone;
IBOutlet UITextView *textView;
UITabBarController* tabBarController; // set from superview in AppDelegate (MainWindow.xib)
}
@property (nonatomic, retain) UITabBarController* tabBarController;
FirstViewController.m:
@synthesize tabBarController;
- (void)viewDidAppear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShown:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)moveTextViewForKeyboard:(NSNotification*)aNotification up:(BOOL)up {
NSDictionary* userInfo = [aNotification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardEndFrame;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
CGRect newFrame = textView.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
keyboardFrame.size.height -= tabBarController.tabBar.frame.size.height;
newFrame.size.height -= keyboardFrame.size.height * (up?1:-1);
textView.frame = newFrame;
[UIView commitAnimations];
}
- (void)keyboardWillShown:(NSNotification*)aNotification
{
buttonDone.enabled = true;
[self moveTextViewForKeyboard:aNotification up:YES];
}
- (void)keyboardWillHide:(NSNotification*)aNotification
{
buttonDone.enabled = false;
[self moveTextViewForKeyboard:aNotification up:NO];
}
P.S. It's hard to code for iOS without stackoverflow...
With Auto Layout, it's much easier (provided you understand Auto Layout) to handle:
Instead of trying to identify and resize the affected views, you simply create a parent frame for all your view's contents. Then, if the kbd appears, you resize the frame, and if you've set up the constraints properly, the view will re-arrange all its child views nicely. No need to fiddle with lots of hard-to-read code for this.
In fact, in a similar question I found a link to this excellent tutorial about this technique.
I ran into several issues trying to get my text view to scroll and animate correctly for both iOS 7 and iOS 8, and with the new QuickType feature. At first I was focused on animating the scroll view insets, but the behaviour differed between iOS 7 and 8 and could not get it working correctly for both.
Then I realized I can simplify things by just focusing on the frame and this worked for me with a lot more simple code. In summary:
UIKeyboardDidChangeFrameNotification
(this will notify when the QuickType is shown/hidden as well).Here is some code that illustrates the above:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidChangeFrameWithNotification:) name:UIKeyboardDidChangeFrameNotification object:nil];
}
- (void)keyboardDidChangeFrameWithNotification:(NSNotification *)notification {
CGFloat keyboardVerticalIncrease = [self keyboardVerticalIncreaseForNotification:notification];
[self animateTextViewFrameForVerticalOffset:keyboardVerticalIncrease];
}
- (CGFloat)keyboardVerticalIncreaseForNotification:(NSNotification *)notification {
CGFloat keyboardBeginY = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].origin.y;
CGFloat keyboardEndY = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;
CGFloat keyboardVerticalIncrease = keyboardBeginY - keyboardEndY;
return keyboardVerticalIncrease;
}
- (void)animateTextViewFrameForVerticalOffset:(CGFloat)offset {
CGFloat constant = self.bottomConstraint.constant;
CGFloat newConstant = constant + offset;
self.bottomConstraint.constant = newConstant;
[self.view layoutIfNeeded];
[UIView animateWithDuration:0.5 animations:^{
[self.view layoutIfNeeded];
}];
}
A quick note on the animation. I used Autolayout so I chose to animate the text view's NSAutoLayoutConstraint, not the frame directly. And to do this, I call [self.view layoutIfNeeded]
before and inside the animation block. This is the correct way of animating constraints. I found this tip here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With