I have an application with a UITableView that has UITextFields inside UITableViewCells which the user will have either the virtual UIKeyboard or a Bluetooth keyboard connected to enter text into the UITextFields.
If the Bluetooth keyboard is connected I would like to keep the UITableView full height when selecting and entering text. When there is no Bluetooth keyboard connected if its visible I would like to reduce the UITableview to fit with the UIkeyboard is showing, if its not showing then I would like to make the UITableView full size again.
I have tried to do this by using the UIKeyboard delegate methods
- (void)keyboardDidShow:(NSNotification *)aNotification;
- (void)keyboardDidHide:(NSNotification *)aNotification;
For some reason keyboardDidShow is not accessed ever but keyboardDidHide is accessed when the UIKeyboard is removed from view and I cannot figure out why.
- (void)keyboardDidShow:(NSNotification *)aNotification;
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.3f];
self.tblView.frame = CGRectMake(0, height, self.view.frame.size.width, self.view.frame.size.height - 255); // or -216
[UIView commitAnimations];
}
- (void)keyboardDidHide:(NSNotification *)aNotification;
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.2f];
self.tblView.frame = CGRectMake(0, height, self.view.frame.size.width, self.view.frame.size.height - height);
[UIView commitAnimations];
}
And in UITextField Delegate Methods
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
CGRect rc = [textField bounds];
rc = [textField convertRect:rc toView:self.tblView];
CGPoint pt = rc.origin;
pt.x = 0;
if(rc.origin.y > 200)
pt.y -= 150;
else
pt.y -= rc.origin.y;
[self.tblView setContentOffset:pt animated:YES];
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
use optimized way like this
selectRowAtIndexPath:animated:scrollPosition:
Selects a row in the receiver identified by index path, optionally scrolling the row to a location in the receiver.
- (void)selectRowAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UITableViewScrollPosition)scrollPosition
Special Considerations
Passing UITableViewScrollPositionNone will result in no scrolling, rather than the minimum scrolling described for that constant. To scroll to the newly selected row with minimum scrolling, select the row using this method with UITableViewScrollPositionNone, then call scrollToRowAtIndexPath:atScrollPosition:animated: with UITableViewScrollPositionNone.
NSIndexPath *rowToSelect; // assume this exists and is set properly
UITableView *myTableView; // assume this exists
[myTableView selectRowAtIndexPath:rowToSelect animated:YES scrollPosition:UITableViewScrollPositionNone];
[myTableView scrollToRowAtIndexPath:rowToSelect atScrollPosition:UITableViewScrollPositionNone animated:YES];
more understand Setting scroll position in UITableView
Related
I am trying to use this code
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(#"%f",self.view.frame.origin.y);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25f];
CGRect frame = self.view.frame;
frame.origin.y =frame.origin.y -204;
[self.view setFrame:frame];
[UIView commitAnimations];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25f];
CGRect frame = self.view.frame;
frame.origin.y = frame.origin.y + 204;
[self.view setFrame:frame];
[UIView commitAnimations];
}
To move view up when keyboard is present but this results like this:
becomes this:
Can't figure out why and if it has to do something with the navbar or constraints.
Why not to use this beautiful library named IQKeyboardManager. Just add it through pods/manually and let it do your work
Kind of what Alexey Sobolevsky said did the trick. Basically i needed to put them in a scrollview and add a constraint from the scroll view to the object beneath, then put all the views containing textfields inside that scrollview instead. This made everything work correctly.
First add the scroll view.
Then write the following code.
//When return key press then bring the view back
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
self.scrlView.contentOffset = CGPointMake(0, 0);
return YES;
}
//When the text field begin editing then moves the view up
-(void)textFieldDidBeginEditing:(UITextField *)textField{
self.scrlView.contentOffset = CGPointMake(0, 30);
}
//When ext field end editing then bring the view back
-(void)textFieldDidEndEditing:(UITextField *)textField{
self.scrlView.contentOffset = CGPointMake(0, 0);
}
I have UITableView with UITextfields as the subview in contentView.
They work and all, but when I select the bottom ones, they are getting covered by the keyboard, so I want the UITableView to scroll up.
Here is my current code:
-(void)keyboardWillShow:(NSNotification*)notification {
NSValue *keyboardFrameValue = [[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardFrame = [[self view] convertRect:[keyboardFrameValue CGRectValue] fromView:nil];
[UIView animateWithDuration:0.3 animations:^{
[constraint setConstant:keyboardFrame.size.height];
[self.myTableView layoutIfNeeded];
}];
}
-(void)keyboardWillHide:(NSNotification *)notification {
[UIView animateWithDuration:0.3 animations:^{
[constraint setConstant:0];
[self.myTableView layoutIfNeeded];
}];
}
The problem with this is that it messes up the data, textfields are being added to the wrong Cells and stuff.
Hope that anyone can help out.
If possible, use an UITableViewController, the keyboard is handled automatically.
Otherwise, adjust the contentInset property of the table view as outlined by Apple.
I've been following this and a bunch of other tutorials/blogs,etc trying to get my view to scroll when the user hits "return" and ends on a UITextField that is being covered by the keyboard but nothing is actually working.
I'm wondering what must I be doing or missing that is causing this?
Basically:
the user wants to do something in the app: add a credit card
show a UIView that contains all the CC fields
1/2 of the UITextFields are covered by the keyboard
scroll the view when the user gets there.
Nothing is happening. The code for detecting the 'covered by keyboard' case is being hit and executed but: [self.scrollView setContentOffset:scrollPoint animated:YES] has no effect at all.
Thoughts?
Reveal screenshot:
code: same as the tutorial in the link. Nothing new there.
Did you check the contentSize property?
To make a scroll view scrollable, the content must be larger than the display area(usually the bounds of the scrollview).
You can achieve this by explicitly setting the contentSize property which is CGSizeZero by default
In addition, setting the contentInset property to adjust the size of display area(in this case you can set bottom value equals keyboard height) when the keyboard is popped up
Try this,
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[UIView animateWithDuration:0.25 animations:^{
[yourTextField setFrame:CGRectMake(yourTextField.frame.origin.x, yourTextField.frame.origin.y-keyboardHeight, yourTextField.frame.size.width, yourTextField.frame.size.height)];
}];
}
and
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView animateWithDuration:0.25 animations:^{
[yourTextField setFrame:CGRectMake(yourTextField.frame.origin.x, yourTextField.frame.origin.y+keyboardHeight, yourTextField.frame.size.width, yourTextField.frame.size.height)];
}];
}
What I do to avoid the textField being covered by the keyboard is to animate the textfield to the top of the screen when the user touches it to start entering something with the keyboard and animate it back when done. It is much more elegant in my opinion. Maybe that could be an alternative solution for you... I do it for the different screensizes with different numbers... you might need to adjust it of course...
So listen to the textField delegate and in
- (void)textFieldDidBeginEditing:(UITextField *)textField {
you do
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 480){
({[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = -196; [self.view setFrame:frame]; [UIView commitAnimations];});
}
if(result.height == 568){
({[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = -196; [self.view setFrame:frame]; [UIView commitAnimations];});
}
if(result.height == 667){
({[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = -238; [self.view setFrame:frame]; [UIView commitAnimations];});
}
if(result.height == 736){
({[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = -251; [self.view setFrame:frame]; [UIView commitAnimations];});
}
and in
- (void)textFieldDidEndEditing:(UITextField *)textField {
you just animate back
({[UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.35f]; CGRect frame = self.view.frame; frame.origin.y = 0; [self.view setFrame:frame]; [UIView commitAnimations];});
I have a problem, when i put a text field in a simple view.
The keyboard overlaps the view, how can i make than the keyboard push the view?
I have to set an scrollview?
use this, hopping that ur textview in a scrollview and tag of it is 99
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
UIScrollView *MyscrollView = (UIScrollView *)[self.view viewWithTag:99];
[UIView animateWithDuration:1.0f animations:^(void){
[MyscrollView setContentOffset:CGPointMake(0, 40) animated:YES];
}];
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView animateWithDuration:1.0f animations:^(void){
UIScrollView *MyscrollView = (UIScrollView *)[self.view viewWithTag:99];
[MyscrollView setContentOffset:CGPointMake(0, 0) animated:YES];
}];
[textField resignFirstResponder];
}
I have this code to hide UIPickerView by default:
- (void)viewDidLoad
{
[super viewDidLoad];
[_memberList setAlpha:0];
}
and this code to show UIPickerView when a button tapped :
- (IBAction)buttonChooseMember {
[UIView animateWithDuration:0.6 delay:0. options:UIViewAnimationOptionCurveEaseInOut animations:^{
[_memberList setAlpha:1];
} completion:nil];
}
and the last thing is this, to hide keyboard when user tap anywhere :
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UIView * txt in self.view.subviews){
if ([txt isKindOfClass:[UITextField class]]) {
[txt resignFirstResponder];
}else if ([txt isKindOfClass:[UIPickerView class]]) {
[UIView animateWithDuration:0.6 delay:0. options:UIViewAnimationOptionCurveEaseInOut animations:^{
[_registerMLMList setAlpha:0];
} completion:nil];
}
}
}
but all of this just give me 'appear' animation, because it's only changing Alpha value from 0 to 1 (and vice versa). not slide-up or slide-down just like iOS keyboard.
I tried to use this animation below to have iOS keyboard look and feel on my UIPickerView :
- (IBAction)hidePicker {
UIPickerView *pickerView = [[UIPickerView alloc] init]; // default frame is set
float pvHeight = pickerView.frame.size.height;
float y = _screen.bounds.size.height - (pvHeight * -2); // the root view of view controller
[UIView animateWithDuration:0.5f delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.picker.frame = CGRectMake(0 , y, pickerView.frame.size.width, pvHeight);
} completion:nil];
}
- (IBAction)showPicker {
UIPickerView *pickerView = [[UIPickerView alloc] init]; // default frame is set
float pvHeight = pickerView.frame.size.height;
float y = _screen.bounds.size.height - (pvHeight); // the root view of view controller
[UIView animateWithDuration:0.5f delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
self.picker.frame = CGRectMake(0 , y, pickerView.frame.size.width, pvHeight);
} completion:nil];
}
I like this animation, it looks like iOS keyboard animation, but the problem with this animation is... when my app is loaded, the UIPickerView is already shows up. how to hide it when it loads up for the first time?
thank you.
All UIResponder objects have an inputView property. The inputView of a UIResponder is the view that will be shown in place of the keyboard when the responder becomes the first responder.
So if you want a UIPickerView to show up instead of the keyboard, you could simply do it by making your UIResponder (like a UITextField) have a UIPickerView as its inputView.
(As a caveat: you probably won't want a bare UIPickerView as the inputView, because you also need to account for when the keyboard would change size, like when you rotate. But this is the general idea.)
In viewDidLoad take one boolean variable and set it's value as TRUE and also set the UIPickerView's frame so that UIPickerView is invisible for first time.Based on the boolean value handle the frame animations to show or hide the picker view.
hidepicker and showpicker method idea is good, and the problem of "UIPicker is visible when the app is loaded" can be overcome by just setting the frame of UIPickerView while initiating it to the position such that it should not be visible...after that you can call the showpicker method to show the picker view.