I'm trying to resize my UITextView when the keyboard appears, but I don't know what I'm doing wrong.
I have these three lines of code called when the keyboard appears:
CGSize kbSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
textView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height-kbSize.height);
NSLog(#"%f,%f,%f,%f", textView.frame.origin.x, textView.frame.origin.y, textView.frame.size.width, textView.frame.size.height);
For some really odd reason my keyboard doesn't appear and here is what is logged:
0.000000,-180.000000,480.000000,180.000000
Why is the CGRects y origin getting set to -180 when it is hardcoded in at 0?
EDIT: textView is a UITextView I created programatically. I didn't use Interface Builder.
EDIT2: It seems that the problem is that the view is autoresizing when rotated.
You can try this :
- (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];
}
Hope it'll help
Related
For some reason my view is not animating:
- (void)keyboardWillShow:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
double duration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
int curve = [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
int height = self.view.bounds.size.height - kbSize.height+self.tabBarController.tabBar.frame.size.height;
self.notesView.frame = CGRectMake(0, -height,
self.view.bounds.size.width, height);
[UIView animateWithDuration:1.5 delay:0 options:curve animations:^{
self.notesView.frame = CGRectMake(0, 0, self.view.bounds.size.width, height);
} completion:nil];
}
The notesView is being displayed but not animated. When I move the animation code into a btnPressed method then it animates as expected. Any ideas?
Edit
It looks like the method is being called twice (that's a separate problem dealing with the inputAccessoryView that I still need to figure out). I updated it to see if calling the animateWithDuration code only once would solve the problem. However, it's still not animating.
- (void)keyboardWillShow:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
int curve = [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
int height = self.view.bounds.size.height - kbSize.height + self.tabBarController.tabBar.frame.size.height;
if (height == 510) return; //for some reason the self.view.bounds.size.height is different between the two calls
self.notesView.frame = CGRectMake(0, -height, self.view.bounds.size.width, height);
[UIView animateWithDuration:1.5 delay:0 options:curve animations:^{
self.notesView.frame = CGRectMake(0, 0, self.view.bounds.size.width, height);
} completion:nil];
}
I have a UILabel that I show / hide. I want to show the label, pause for a few seconds and hide it. This code ISN'T working. It removes the view as soon as the animation finished (instantly)
-(void) show
{
[UIView animateWithDuration:.5f delay:0.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect newFrame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 44.0f);
self.frame = newFrame;
} completion:^(BOOL finished){
[self hideAndRemove];
}];
}
-(void) hideAndRemove
{
[UIView animateWithDuration:.5f delay:2.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect frame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 0.0f);
self.frame = frame;
} completion:^(BOOL finished){
// nothing
}];
}
However, if I try some other animation on the frame, the delay works and the frame change is animated:
-(void) show
{
[UIView animateWithDuration:.5f delay:0.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect newFrame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 44.0f);
self.frame = newFrame;
} completion:^(BOOL finished){
[self hideAndRemove];
}];
}
-(void) hideAndRemove
{
[UIView animateWithDuration:.5f delay:2.0f
options:UIViewAnimationOptionCurveEaseIn animations:^{
CGRect frame = CGRectMake(0.0f, 64.0f, [UIScreen mainScreen].bounds.size.width, 250.0f);
self.frame = frame;
} completion:^(BOOL finished){
// nothing
}];
}
I don't know what the problem might be, but I think it comes from the frame height who shouldn't be set to 0.
Why not using [UILabel setAlpha:0] to hide your label, and [UILabel setAlpha:1] to show it back ? It seems cleaner than changing its frame height to 0, and it animates nicely.
I'm moving an image with CABasicAnimation, but I've noticed that its rect for touch events remain at its old position - How can I update the rect so it doesn't register at the wrong place?
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:#"transform.translation.x"];
theAnimation.duration=0.3;
theAnimation.repeatCount=0;
theAnimation.fillMode = kCAFillModeForwards;
theAnimation.removedOnCompletion = NO;
theAnimation.autoreverses=NO;
theAnimation.fromValue=[NSNumber numberWithFloat:0];
theAnimation.toValue=[NSNumber numberWithFloat:-rect.size.width*0.9];
[self.layer addAnimation:theAnimation forKey:#"animateLayer"];
In this case, you need to be moving the TouchImageView subclass of the UIImageView, not self.layer. The latter is a lower-level drawing surface, but not what handles the touch events, etc.
From iPad: Move UIView with animation, then move it back, here's some adapted code that animates the translation property as you were doing:
CGFloat moveX = -rect.size.width*0.9;
CGFloat moveY = 0;
[UIView beginAnimations: #"Move View" context:nil];
[UIView setAnimationDuration: 0.3 ];
self.transform = CGAffineTransformMakeTranslation(moveX,moveY);
[UIView commitAnimations];
You should, however, be able to simplify this by just changing the frame of the view:
CGRect newFrame = self.frame;
newFrame.x -=rect.size.width*0.9;
[UIView beginAnimations: #"Move View" context:nil];
[UIView setAnimationDuration: 0.3 ];
self.frame = newFrame;
[UIView commitAnimations];
How do I make sure that the textview is shown and the keyboard is not obscuring the textview, while in landscape.
Using UICatalog I created a TextViewController which works. In it there are two methods for calling the keyboard and making sure that textView is positioned above the keyboard. his just works great in Portrait mode.
I got the Landscape mode working, but on the textView is still being put to the top of the iPhone to compensate for the keyboard in portrait mode.
I changed the methods for showing the keyboards.
Below is the code for this methods: (I will just let see the code for show, since the hide code will be the reverse..
- (void)keyboardWillShow:(NSNotification *)aNotification
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait) {
// the keyboard is showing so resize the table's height
CGRect keyboardRect = [[[aNotification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];
NSTimeInterval animationDuration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.size.height -= keyboardRect.size.height;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
} else if (orientation == UIInterfaceOrientationLandscapeLeft) {
NSLog(#"Left"); // Verijderen later
CGRect keyboardRect = [[[aNotification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];
NSTimeInterval animationDuration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.size.width -= keyboardRect.size.height;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
} else if (orientation == UIInterfaceOrientationLandscapeRight){
NSLog(#"Right"); // verwijderen later.
CGRect keyboardRect = [[[aNotification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue];
NSTimeInterval animationDuration = [[[aNotification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.view.frame;
frame.size.width -= keyboardRect.size.width;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
}
}
I know that I have to change the line frame.size.height -= keyboardRect.size.height but I do not seem to get it working.
I tried frame.size.width -= keyboardRect.size.height that did not work. Losing the keyboardRect and frame all together work, however off course the keyboard obscures the textview........
I found the above code wouldn't work when in Landscape Mode on iPad
Note: I am moving all Fields, as in my case that's what i needed :-)
- (void)keyboardWillShow:(NSNotification*)aNotification {
// Only do for Landscape Mode
if (UIInterfaceOrientationIsLandscape([self interfaceOrientation])){
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.x -= keyboardSize.height-44;
frame.origin.y -= keyboardSize.height-44;
frame.size.height += keyboardSize.height-44;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = YES;
}
keyboardInUse = YES;
}
- (void)keyboardWillHide:(NSNotification*)aNotification {
if (UIInterfaceOrientationIsLandscape([self interfaceOrientation])){
if (viewMoved) {
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y += keyboardSize.height-44;
frame.origin.x += keyboardSize.height-44;
frame.size.height -= keyboardSize.height-44;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = NO;
}
}
keyboardInUse = NO;
}
If you think you need different code for the different orientations, you're doing something else wrong. Once the orientation has changed and your superview has responded, the value that needs changing should always be the frame's height.
Here is a code that I use for this purpose. It works on both iPad and iPhone is landscape and portrait modes (inspired by a code from Apple documentation):
// 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*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
float offset;
if UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
offset = kbSize.height;
else
offset = kbSize.width;
[UIView animateWithDuration:0.5
animations:^{
CGRect frameTxtField = myTextField.frame;
frameTxtField.origin.y -= offset;
myTextField.frame = frameTxtField;
}
];
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
float offset;
if UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
offset = kbSize.height;
else
offset = kbSize.width;
[UIView animateWithDuration:0.5
animations:^{
CGRect frameTxtField = myTextField.frame;
frameTxtField.origin.y += offset;
myTextField.frame = frameTxtField;
}
];
}
Don't forget to call the registerForKeyboardNotifications method (e.g., in viewDidLoad).
I have a table with each cell containing a label and a text field. Problem is that when i go to edit the last row, keyboard hides the lower portion of the table, and i can't see what is being typed. How can i move my interface above the keyboard so i see what is being typed?
Thanks,
Mustafa
You'll want to register your viewController for UIKeyboardDidShowNotification and UIKeyboardWillHideNotification events. When you get these, you should adjust the bounds of your table; the keyboard is 170 pixels height, so just shrink or grow your table bounds appropriately, and it should properly adjust to the keyboard.
This problem is complex depending on your UI scenario. Here I will discuss a scenario that where UITextField or UITextview resides in a UITableViewCell.
You need to use NSNotificationCenter to detect UIKeyboardDidShowNotification event.
see http://iosdevelopertips.com/user-interface/adjust-textfield-hidden-by-keyboard.html. You need to shrink the UITableView frame size so that it occupies only the screen area that is not covered by the keyboard.
If you tap a UITableViewCell, the OS will automatically position the cell within the viewing area of UITableView. But it does not happen when you tap a UITextView or UITableViewCell even though it resides in a UITableViewCell.
You need to call
[myTableView selectRowAtIndexPath:self.indexPath animated:YES scrollPosition:UITableViewScrollPositionBottom];`
to programmatically "tap" the cell.
If you implement both points, you will see the UITextView/Field position right above the keyboard. Bare in mind that the UITableViewCell where the UITableView/Field resides cannot be taller than the "not covered" area. If this is not the case for you, there is a different approach for it but I will not discuss here.
Check out this question: A UITableView list of editable text fields
Just make sure that you have enough scrolling space below that. Because according to my knowledge the iPhone automatically adjusts and shows the focused textbox at the time its keyboard appears.
Removing/commenting the lines where the rect hight is being modified seems to solve the problem. Thanks.
Modified Code:
# define kOFFSET_FOR_KEYBOARD 150.0 // keyboard is 150 pixels height
// Animate the entire view up or down, to prevent the keyboard from covering the author field.
- (void)setViewMovedUp:(BOOL)movedUp
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
// Make changes to the view's frame inside the animation block. They will be animated instead
// of taking place immediately.
CGRect rect = self.view.frame;
CGRect textViewRect = self.textViewBeingEdited.frame;
CGRect headerViewRect = self.headerView.frame;
if (movedUp) {
// If moving up, not only decrease the origin but increase the height so the view
// covers the entire screen behind the keyboard.
rect.origin.y -= kOFFSET_FOR_KEYBOARD;
// rect.size.height += kOFFSET_FOR_KEYBOARD;
} else {
// If moving down, not only increase the origin but decrease the height.
rect.origin.y += kOFFSET_FOR_KEYBOARD;
// rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
self.view.frame = rect;
[UIView commitAnimations];
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification
object:nil];
keyboardVisible = NO;
- (void)keyboardWasShown:(NSNotification *)aNotification {
if ( keyboardVisible )
return;
if( activeTextField != MoneyCollected)
{
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y -= keyboardSize.height-300;
frame.size.height += keyboardSize.height-50;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = YES;
}
keyboardVisible = YES;
}
- (void)keyboardWasHidden:(NSNotification *)aNotification {
if ( viewMoved )
{
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y += keyboardSize.height-300;
frame.size.height -= keyboardSize.height-50;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = NO;
}
keyboardVisible = NO;
}
tabelview.contentInset = UIEdgeInsetsMake(0, 0, 210, 0);
[tableview scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:your_indexnumber inSection:Your_section]
atScrollPosition:UITableViewScrollPositionMiddle animated:NO];
try this my coding this will help for u