Hello i am facing a problem with UITextView.
In my app , i need to support both Portrait and Landscape.
So i added UITextView into my app and resize the frame of UITextView when keyboard appearing with following code because when keyboard appear , the UITextView is behind the keyboard and i can't see what i write in UITextView.
- (void)keyboardWillShow:(NSNotification*)notification
{
[self moveTextViewForKeyboard:notification up:YES];
}
- (void)keyboardWillHide:(NSNotification*)notification
{
[self moveTextViewForKeyboard:notification up:NO];
}
- (void)moveTextViewForKeyboard:(NSNotification*)notification up:(BOOL)up {
NSDictionary *userInfo = [notification userInfo];
NSTimeInterval animationDuration;
UIViewAnimationCurve animationCurve;
CGRect keyboardRect;
[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
keyboardRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
if (up == YES)
{
CGFloat keyboardTop = keyboardRect.origin.y;
CGRect newTextViewFrame = self.txtView.frame;
newTextViewFrame.size.height = keyboardTop - self.txtView.frame.origin.y - 10;
self.txtView.frame = newTextViewFrame;
}
else
{
self.txtView.frame = originalCGRect;
}
[UIView commitAnimations];
}
That is fine when keyboard appear and not covering my UITextView anymore.
However when i rotate into Landscape , the UITextView frame is not correct anymore and also when i hide keyboard , it still remain like small size and not the fit with View.
How can i solve that problem?
Please help me.
Try this i hope helpful to you....
Related
I am facing very strange situation. I want to scroll-up the UIScrollView to visible when keyboard appear on some UITextView, and this part of the code is working fine. But when keyboard disappears, scrollView do not come to its original position. When I drag it then it come to its original position. Following is what I have done. Please guide me what I have missed
- (void)keyboardWillHide:(NSNotification *)notification {
NSDictionary* info = [notification userInfo];
kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect commentViewFrame = self.detailCommentView.frame;
commentViewFrame.origin.y += kbSize.height;
[UIView animateWithDuration:0.3 animations:^{
[self.detailCommentView setFrame:commentViewFrame];
self.scrollView.contentOffset = CGPointMake(0, self.detailCommentView.frame.origin.y - 90);
} completion:^(BOOL finished) {
}];
}
- (void)keyboardWillShow:(NSNotification *)notification {
NSDictionary* info = [notification userInfo];
kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect commentViewFrame = self.detailCommentView.frame;
commentViewFrame.origin.y -= kbSize.height;
[UIView animateWithDuration:0.3 animations:^{
[self.detailCommentView setFrame:commentViewFrame];
self.scrollView.contentOffset = CGPointMake(0, self.detailCommentView.frame.origin.y + 90);
} completion:^(BOOL finished) {
}];
}
I'd blindly try using UIKeyboardFrameEndUserInfoKey instead of UIKeyboardFrameBeginUserInfoKey to see if it works.
Otherwise I'd check whether commentViewFrame value is correct when you're hiding the keyboard.
There is also one more thing that I don't know whether is correct. In keyboardWillShow you're referencing self.detailCommentView.frame.origin.y but in keyboardWillHide you're referencing self.dopDetailCommentView.frame.origin.y. Is it alright?
I have found the solution. Actually the concept behind scrollview was not clear to me. But now it is clear and change in one line only made the trick.
- (void)keyboardWillHide:(NSNotification *)notification {
NSDictionary* info = [notification userInfo];
kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect commentViewFrame = self.detailCommentView.frame;
commentViewFrame.origin.y += kbSize.height;
[UIView animateWithDuration:0.3 animations:^{
[self.detailCommentView setFrame:commentViewFrame];
self.scrollView.contentOffset = CGPointMake(0, 0);
} completion:^(BOOL finished) {
}];
}
I have a UIViewController with a main view. Within that view I have a red UIView that has a UITextView inside, that I would like to grow vertically when text is written. I'm able to have this effectively done if the redView initially starts somewhere in the middle of the screen and doesn't move based on the keyboard popping up by just modifying the UITextViewHeightConstraint that I made.
-(void)textViewDidChange:(UITextView *)textView {
[self.textView setScrollEnabled:NO];
CGSize newSize = [textView sizeThatFits:CGSizeMake(textView.frame.size.width, 999)];
if (newSize.height > textView.frame.size.height) {
self.textViewHeight.constant = newSize.height;
}
}
When I dock the redView that includes the UITextView subview to the bottom of the screen, my code appropriately will bring the view above the keyboard nicely, using the following code:
-(void)adjustViewForKeyboardNotification:(NSNotification *)notification {
NSDictionary *notificationInfo = [notification userInfo];
CGRect finalKeyboardFrame = [[notificationInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
//Get AnimationCurve and AnimationDuration for keyboard popping up.
UIViewAnimationCurve animationCurve = (UIViewAnimationCurve) [[notificationInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
NSTimeInterval animationDuration = [[notificationInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
finalKeyboardFrame = [self.view convertRect:finalKeyboardFrame fromView:self.view.window];
CGRect textBarFrame = self.redView.frame;
textBarFrame.origin.y = finalKeyboardFrame.origin.y-textBarFrame.size.height;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];
[UIView setAnimationBeginsFromCurrentState:YES];
self.redView.frame = textBarFrame;
[UIView commitAnimations];
}
However, when I start typing and it comes time for the UITextView to expand, the redView is sent back down and is docked to the bottom of the screen (under the keyboard) - where it then expands vertically as I would have liked. I've tried adjusting the constraints in many different ways but haven't found a solution. I've tried setting the frame of the redView manually but that doesn't seem to work either (likely because of auto layout being enabled).
Any advice or tips would be greatly appreciated!
I am using UITableView (chatTable) along with UITabBar (chatTabBar) and one textField inside imageView. I am using autolayout. I used the following code to change the views when keyboard appears and disappears.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
// get animation info from userInfo
NSTimeInterval animationDuration;
CGRect keyboardFrame;
[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardFrame];
// resize the frame
[UIView animateWithDuration:animationDuration delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.keyboardHeight.constant = keyboardFrame.size.height - TABBAR_HEIGHT ;
[self.view layoutIfNeeded];
} completion:nil];
if ([chatData count] != VALUE_ZERO)
{
[chatTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:([chatData count] - VALUE_ONE) inSection:VALUE_ZERO] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}
}
- (void)keyboardWillHide:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
// get animation info from userInfo
NSTimeInterval animationDuration;
CGRect keyboardFrame;
[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardFrame];
// Set view frame
[UIView animateWithDuration:animationDuration delay:2.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.keyboardHeight.constant -= keyboardFrame.size.height - TABBAR_HEIGHT;
[self.view layoutIfNeeded];
} completion:nil];
}
Now when I press return the tableview goes up a littel bit (from screen 2 to screen 3). keyboardHeight is the bottom space constraint between the tabBar and main view.
(screen 2)
(screen3)
I have tried many things but I can't able to find why the tableview is going up for a while. (problem is there is no smooth animation.) (Note: I have put delay as 2.0 only to show what happens in following screenshot(screen 3) othewise it's value would be 0)
Your problem is that you're changing the table view frame when the keyboard appears, which is wrong. You need to change the contentInset property of the table view, instead of meddling with frames.
- (void)keyboardWillShow:(NSNotification *)notification {
CGFloat height = [notification.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height - self.tabBarController.tabBar.frame.size.height;
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0.0f, 0.0f, height, 0.0f);
_tableView.contentInset = edgeInsets;
_tableView.scrollIndicatorInsets = edgeInsets;
}
- (void)keyboardWillHide:(NSNotification *)notification {
UIEdgeInsets edgeInsets = UIEdgeInsetsZero;
_tableView.contentInset = edgeInsets;
_tableView.scrollIndicatorInsets = edgeInsets;
}
Solved the problem with contentInset property. I am using contentInset as mentiond by the #Eugene and also changing the constant property of bottom constraint of the textfiled to move up and doen whenever keyboard is shown and hidden.
I am doing an animation to show the text view on top keyboard when UIKeyboardWillShowNotification is being broadcasted like following
-(void) keyboardWillShow:(NSNotification *)notification{
// get keyboard size and loctaion
NSDictionary *info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
NSNumber *duration = [notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
__block CGRect containerFrame = containerView.frame;
containerFrame.origin.y = self.view.bounds.size.height - (kbSize.height + containerFrame.size.height);
[UIView animateWithDuration:[duration doubleValue]
delay:0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
containerView.frame = containerFrame;
} completion:^(BOOL finished) {
nil;
}
];
}
An animation is not good enough.If you can give it a try and will see small issue at the end of animation.
I googled and found out that there is another way to do an animation and it works perfectly :
-(void) keyboardWillShow:(NSNotification *)note{
// get keyboard size and loctaion
CGRect keyboardBounds;
[[note.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue: &keyboardBounds];
NSNumber *duration = [note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSNumber *curve = [note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey];
// Need to translate the bounds to account for rotation.
keyboardBounds = [self.view convertRect:keyboardBounds toView:nil];
// get a rect for the textView frame
CGRect containerFrame = containerView.frame;
containerFrame.origin.y = self.view.bounds.size.height - (keyboardBounds.size.height + containerFrame.size.height);
// animations settings
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:[duration doubleValue]];
[UIView setAnimationCurve:[curve intValue]];
// set views with new info
containerView.frame = containerFrame;
// commit animations
[UIView commitAnimations];
}
However, according to the documentation, we are not recommended to use this animation in Ios 4 and later on...
I can not tell any differences between my codes compared to the latter one. Why my codes can not do perfect animation. Please help if you have any ideas.
It's the animation curve. The example you cite is matching its animation curve as well its duration to those of the keyboard. Your code doesn't. Your structure should look more like this:
NSNumber* curve = info[UIKeyboardAnimationCurveUserInfoKey]; // *
NSNumber* duration = info[UIKeyboardAnimationDurationUserInfoKey];
[UIView animateWithDuration:duration.floatValue delay:0
options:curve.integerValue << 16 // *
animations: ^{ // ...
This code is seen a lot on Stack overflow and the internet in general. It is used to adjust the size of a text view so you can see all the content. It was working fine for me then stopped working.(i.e. As once the frame changed and could scroll, now it does nothing.) Does any one have a suggestion as to why this stopped working and how to fix it.
I have confirmed in multiple places (using NSLog) that it does get called.
-(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 = indexCardText.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
keyboardFrame.size.height -= self.tabBarController.tabBar.frame.size.height;
newFrame.size.height -= keyboardFrame.size.height * (up?1:-1);
indexCardText.frame = newFrame;
[UIView commitAnimations];
}
Thanks!
Let me know if this method helps you, I also uploaded the demo to Github.
It is about resizing a UITextView, but can be applied to other object, when keyboard is shown.
https://stackoverflow.com/a/18642479/1363634